Audio recording can now about all audio rates ZSNES supports for PAL and NTSC at stereo. Audio writing buffering removed for now. Fixed bug when writing 32000Hz at PAL.
This commit is contained in:
@@ -1848,21 +1848,26 @@ Code for dumping raw video
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define RAW_BUFFER_SAMPLES 12800
|
|
||||||
#define RAW_WIDTH 256
|
#define RAW_WIDTH 256
|
||||||
#define RAW_HEIGHT 224
|
#define RAW_HEIGHT 224
|
||||||
|
|
||||||
//NTSC FPS is 59.948743718592964824120603015060 in AVI that's a fraction of 59649/995
|
//NTSC FPS is 59.948743718592964824120603015060 in AVI that's a fraction of 59649/995
|
||||||
//which equals 59.948743718592964824120603015075, so videos should not desync for several millinium
|
//which equals 59.948743718592964824120603015075, so videos should not desync for several millinium
|
||||||
|
|
||||||
//FPS = 64000 / Samples per Frame
|
//FPS = Rate*Stereo / Samples per Frame
|
||||||
|
|
||||||
//These two numbers help with calculating how many samples are needed per frame
|
//These two numbers help with calculating how many samples are needed per frame
|
||||||
//59.948743718592964824120603015060 = SAMPLE_NTSC_HI*32000/SAMPLE_NTSC_LO *2
|
//59.948743718592964824120603015060 = SAMPLE_NTSC_LO*Rate/SAMPLE_NTSC_HI
|
||||||
#define SAMPLE_NTSC_HI 31840000ULL
|
//Samples per Frame = SAMPLE_NTSC_HI/SAMPLE_NTSC_LO *Stereo
|
||||||
|
|
||||||
|
#define SAMPLE_NTSC_HI_SCALE 995ULL
|
||||||
#define SAMPLE_NTSC_LO 59649ULL
|
#define SAMPLE_NTSC_LO 59649ULL
|
||||||
|
//Code using this by Bisqwit
|
||||||
//Used by raw videos for calculating sample rate in NTSC mode
|
//Used by raw videos for calculating sample rate in NTSC mode
|
||||||
//Code by Bisqwit
|
|
||||||
|
static const unsigned int freqtab[] = { 8000, 11025, 22050, 44100, 16000, 32000, 48000 };
|
||||||
|
extern unsigned int SoundQuality;
|
||||||
|
#define RATE freqtab[SoundQuality]
|
||||||
|
|
||||||
|
|
||||||
//0 = None; 1 Logging, but not now, 2 Log now
|
//0 = None; 1 Logging, but not now, 2 Log now
|
||||||
@@ -1926,8 +1931,6 @@ struct
|
|||||||
FILE *vp;
|
FILE *vp;
|
||||||
|
|
||||||
FILE *ap;
|
FILE *ap;
|
||||||
unsigned short *sample_buffer;
|
|
||||||
size_t sample_index;
|
|
||||||
|
|
||||||
size_t aud_dsize_pos;
|
size_t aud_dsize_pos;
|
||||||
//These next three are only used for NTSC videos to keep sample rate correct
|
//These next three are only used for NTSC videos to keep sample rate correct
|
||||||
@@ -1955,30 +1958,19 @@ static void raw_video_close()
|
|||||||
|
|
||||||
if (raw_vid.ap)
|
if (raw_vid.ap)
|
||||||
{
|
{
|
||||||
if (raw_vid.sample_buffer)
|
size_t file_size = ftell(raw_vid.ap); //Get file size
|
||||||
|
if (!fseek(raw_vid.ap, 4, SEEK_SET)) //Seek to after RIFF header
|
||||||
{
|
{
|
||||||
size_t file_size;
|
fwrite4(file_size - 8, raw_vid.ap); //Don't include header or this write, -8
|
||||||
if (raw_vid.sample_index)
|
|
||||||
{
|
|
||||||
fwrite(raw_vid.sample_buffer, 2, raw_vid.sample_index, raw_vid.ap); //Sample is 2 bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
free(raw_vid.sample_buffer);
|
|
||||||
|
|
||||||
file_size = ftell(raw_vid.ap); //Get file size
|
|
||||||
if (!fseek(raw_vid.ap, 4, SEEK_SET)) //Seek to after RIFF header
|
|
||||||
{
|
|
||||||
fwrite4(file_size - 8, raw_vid.ap); //Don't include header or this write, -8
|
|
||||||
}
|
|
||||||
if (!fseek(raw_vid.ap, raw_vid.aud_dsize_pos, SEEK_SET)) //Seek to where the audio data size goes
|
|
||||||
{
|
|
||||||
//Data size is remainder of file, which is file size, less current position, plus
|
|
||||||
//The 4 bytes needed to hold the data size
|
|
||||||
fwrite4(file_size - (raw_vid.aud_dsize_pos+4), raw_vid.ap);
|
|
||||||
}
|
|
||||||
fclose(raw_vid.ap);
|
|
||||||
raw_vid.ap = 0;
|
|
||||||
}
|
}
|
||||||
|
if (!fseek(raw_vid.ap, raw_vid.aud_dsize_pos, SEEK_SET)) //Seek to where the audio data size goes
|
||||||
|
{
|
||||||
|
//Data size is remainder of file, which is file size, less current position, plus
|
||||||
|
//The 4 bytes needed to hold the data size
|
||||||
|
fwrite4(file_size - (raw_vid.aud_dsize_pos+4), raw_vid.ap);
|
||||||
|
}
|
||||||
|
fclose(raw_vid.ap);
|
||||||
|
raw_vid.ap = 0;
|
||||||
AudioLogging = 0;
|
AudioLogging = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2014,39 +2006,66 @@ static bool raw_video_open()
|
|||||||
{
|
{
|
||||||
if ((raw_vid.ap = fopen(md_pcm_audio, "wb")))
|
if ((raw_vid.ap = fopen(md_pcm_audio, "wb")))
|
||||||
{
|
{
|
||||||
if ((raw_vid.sample_buffer = (unsigned short *)malloc(RAW_BUFFER_SAMPLES*sizeof(short))))
|
fputs("RIFF", raw_vid.ap); //header
|
||||||
|
fwrite4(~0, raw_vid.ap); //file size - unknown till file close
|
||||||
|
fputs("WAVEfmt ", raw_vid.ap); //format
|
||||||
|
fwrite4(0x12, raw_vid.ap); //fmt size
|
||||||
|
fwrite2(1, raw_vid.ap); //fmt type (PCM)
|
||||||
|
fwrite2(2, raw_vid.ap); //channels
|
||||||
|
fwrite4(RATE, raw_vid.ap); //sample rate
|
||||||
|
fwrite4(RATE*4, raw_vid.ap); //byte rate (sample rate*block align)
|
||||||
|
fwrite2(16/8*2, raw_vid.ap); //block align (SignificantBitsPerSample / 8 * NumChannels)
|
||||||
|
fwrite2(16, raw_vid.ap); //Significant bits per sample
|
||||||
|
fwrite2(0, raw_vid.ap); //Extra format bytes
|
||||||
|
fputs("data", raw_vid.ap); //data header
|
||||||
|
raw_vid.aud_dsize_pos = ftell(raw_vid.ap); //Save current position for use later
|
||||||
|
fwrite4(~0, raw_vid.ap); //data size - unknown till file close
|
||||||
|
|
||||||
|
if (!romispal)
|
||||||
{
|
{
|
||||||
fputs("RIFF", raw_vid.ap); //header
|
raw_vid.sample_ntsc_hi = SAMPLE_NTSC_HI_SCALE*RATE;
|
||||||
fwrite4(~0, raw_vid.ap); //file size - unknown till file close
|
raw_vid.sample_ntsc_lo = SAMPLE_NTSC_LO;
|
||||||
fputs("WAVEfmt ", raw_vid.ap); //format
|
raw_vid.sample_ntsc_balance = raw_vid.sample_ntsc_hi;
|
||||||
fwrite4(0x12, raw_vid.ap); //fmt size
|
|
||||||
fwrite2(1, raw_vid.ap); //fmt type (PCM)
|
|
||||||
fwrite2(2, raw_vid.ap); //channels
|
|
||||||
fwrite4(32000, raw_vid.ap); //sample rate
|
|
||||||
fwrite4(32000*4, raw_vid.ap); //byte rate (sample rate*block align)
|
|
||||||
fwrite2(16/8*2, raw_vid.ap); //block align (SignificantBitsPerSample / 8 * NumChannels)
|
|
||||||
fwrite2(16, raw_vid.ap); //Significant bits per sample
|
|
||||||
fwrite2(0, raw_vid.ap); //Extra format bytes
|
|
||||||
fputs("data", raw_vid.ap); //data header
|
|
||||||
raw_vid.aud_dsize_pos = ftell(raw_vid.ap); //Save current position for use later
|
|
||||||
fwrite4(~0, raw_vid.ap); //data size - unknown till file close
|
|
||||||
|
|
||||||
if (!romispal)
|
|
||||||
{
|
|
||||||
raw_vid.sample_ntsc_hi = SAMPLE_NTSC_HI;
|
|
||||||
raw_vid.sample_ntsc_lo = SAMPLE_NTSC_LO;
|
|
||||||
raw_vid.sample_ntsc_balance = SAMPLE_NTSC_HI;
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioLogging = 1;
|
|
||||||
return(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AudioLogging = 1;
|
||||||
|
return(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
raw_video_close();
|
raw_video_close();
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void raw_audio_write(unsigned int samples)
|
||||||
|
{
|
||||||
|
void ProcessSoundBuffer();
|
||||||
|
extern int DSPBuffer[1280];
|
||||||
|
extern unsigned int BufferSizeB, BufferSizeW;
|
||||||
|
unsigned int i = 0;
|
||||||
|
int temp;
|
||||||
|
|
||||||
|
if (samples > 1280)
|
||||||
|
{
|
||||||
|
raw_audio_write(1280);
|
||||||
|
samples -= 1280;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferSizeB = samples;
|
||||||
|
BufferSizeW = samples<<1;
|
||||||
|
|
||||||
|
AudioLogging = 2;
|
||||||
|
asm_call(ProcessSoundBuffer);
|
||||||
|
AudioLogging = 1;
|
||||||
|
|
||||||
|
for (i = 0; i < BufferSizeB; i++)
|
||||||
|
{
|
||||||
|
temp = DSPBuffer[i];
|
||||||
|
if (temp > 32767) { temp = 32767; }
|
||||||
|
else if (temp < -32768) { temp =-32768; }
|
||||||
|
fwrite2((short)temp, raw_vid.ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define PIXEL (vidbuffer[(i*288) + j + 16])
|
#define PIXEL (vidbuffer[(i*288) + j + 16])
|
||||||
static void raw_video_write_frame()
|
static void raw_video_write_frame()
|
||||||
{
|
{
|
||||||
@@ -2067,45 +2086,26 @@ static void raw_video_write_frame()
|
|||||||
|
|
||||||
if (raw_vid.ap)
|
if (raw_vid.ap)
|
||||||
{
|
{
|
||||||
void ProcessSoundBuffer();
|
unsigned int samples;
|
||||||
extern int DSPBuffer[1280];
|
|
||||||
extern unsigned int BufferSizeB, BufferSizeW;
|
|
||||||
unsigned int i = 0;
|
|
||||||
int temp;
|
|
||||||
|
|
||||||
if (romispal)
|
if (romispal)
|
||||||
{
|
{
|
||||||
BufferSizeB = 1280;
|
samples = RATE*2/50;
|
||||||
|
if (samples & 1)
|
||||||
|
{
|
||||||
|
static signed char odd_carry = 0;
|
||||||
|
samples += odd_carry-1;
|
||||||
|
odd_carry ^= 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Thanks Bisqwit for this algorithm
|
//Thanks Bisqwit for this algorithm
|
||||||
BufferSizeB = (raw_vid.sample_ntsc_balance/raw_vid.sample_ntsc_lo) << 1;
|
samples = (raw_vid.sample_ntsc_balance/raw_vid.sample_ntsc_lo) << 1;
|
||||||
raw_vid.sample_ntsc_balance %= raw_vid.sample_ntsc_lo;
|
raw_vid.sample_ntsc_balance %= raw_vid.sample_ntsc_lo;
|
||||||
raw_vid.sample_ntsc_balance += raw_vid.sample_ntsc_hi;
|
raw_vid.sample_ntsc_balance += raw_vid.sample_ntsc_hi;
|
||||||
//printf("Frame %u: %u samples\n", raw_vid.frame_index, BufferSizeB);
|
//printf("Frame %u: %u samples\n", raw_vid.sample_index, BufferSizeB);
|
||||||
}
|
|
||||||
BufferSizeW = BufferSizeB<<1;
|
|
||||||
|
|
||||||
AudioLogging = 2;
|
|
||||||
asm_call(ProcessSoundBuffer);
|
|
||||||
AudioLogging = 1;
|
|
||||||
|
|
||||||
for (i = 0; i < BufferSizeB; i++)
|
|
||||||
{
|
|
||||||
temp = DSPBuffer[i];
|
|
||||||
if (temp > 32767) { temp = 32767; }
|
|
||||||
else if (temp < -32768) { temp =-32768; }
|
|
||||||
raw_vid.sample_buffer[raw_vid.sample_index] = temp;
|
|
||||||
|
|
||||||
raw_vid.sample_index++;
|
|
||||||
|
|
||||||
if (raw_vid.sample_index == RAW_BUFFER_SAMPLES)
|
|
||||||
{
|
|
||||||
fwrite(raw_vid.sample_buffer, 2, RAW_BUFFER_SAMPLES, raw_vid.ap); //Each sample is 2 bytes
|
|
||||||
raw_vid.sample_index = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
raw_audio_write(samples);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user