diff options
author | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2009-04-01 02:26:34 +0300 |
---|---|---|
committer | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2009-04-01 02:43:47 +0300 |
commit | cf9edda1d370d39bc8a3d020a9c2bc4090d2457e (patch) | |
tree | 1d1bbc529a4e8109fb6aa5cadf0dbbb7bd61013a /libao2 | |
parent | 7af8417ae7beb409f54849956a7037bc66c4c334 (diff) | |
parent | 1c37a6427abef0827c608d328d37ca1b1a0a022d (diff) | |
download | mpv-cf9edda1d370d39bc8a3d020a9c2bc4090d2457e.tar.bz2 mpv-cf9edda1d370d39bc8a3d020a9c2bc4090d2457e.tar.xz |
Merge svn changes up to r29117
Diffstat (limited to 'libao2')
-rw-r--r-- | libao2/ao_pcm.c | 270 |
1 files changed, 138 insertions, 132 deletions
diff --git a/libao2/ao_pcm.c b/libao2/ao_pcm.c index bf3f224e81..b64118ff31 100644 --- a/libao2/ao_pcm.c +++ b/libao2/ao_pcm.c @@ -37,10 +37,10 @@ static const ao_info_t info = { - "RAW PCM/WAVE file writer audio output", - "pcm", - "Atmosfear", - "" + "RAW PCM/WAVE file writer audio output", + "pcm", + "Atmosfear", + "" }; LIBAO_EXTERN(pcm) @@ -60,23 +60,24 @@ static int fast = 0; struct WaveHeader { - uint32_t riff; - uint32_t file_length; - uint32_t wave; - uint32_t fmt; - uint32_t fmt_length; - uint16_t fmt_tag; - uint16_t channels; - uint32_t sample_rate; - uint32_t bytes_per_second; - uint16_t block_align; - uint16_t bits; - uint32_t data; - uint32_t data_length; + uint32_t riff; + uint32_t file_length; + uint32_t wave; + uint32_t fmt; + uint32_t fmt_length; + uint16_t fmt_tag; + uint16_t channels; + uint32_t sample_rate; + uint32_t bytes_per_second; + uint16_t block_align; + uint16_t bits; + uint32_t data; + uint32_t data_length; }; /* init with default values */ static struct WaveHeader wavhdr; +static uint64_t data_length; static FILE *fp = NULL; @@ -88,102 +89,107 @@ static int control(int cmd,void *arg){ // open & setup audio device // return: 1=success 0=fail static int init(int rate,int channels,int format,int flags){ - int bits; - opt_t subopts[] = { - {"waveheader", OPT_ARG_BOOL, &ao_pcm_waveheader, NULL}, - {"file", OPT_ARG_MSTRZ, &ao_outputfilename, NULL}, - {"fast", OPT_ARG_BOOL, &fast, NULL}, - {NULL} - }; - // set defaults - ao_pcm_waveheader = 1; - - if (subopt_parse(ao_subdevice, subopts) != 0) { - return 0; - } - if (!ao_outputfilename){ - ao_outputfilename = - strdup(ao_pcm_waveheader?"audiodump.wav":"audiodump.pcm"); - } - - bits=8; - switch(format){ - case AF_FORMAT_S32_BE: - format=AF_FORMAT_S32_LE; - case AF_FORMAT_S32_LE: - bits=32; - break; - case AF_FORMAT_FLOAT_BE: - format=AF_FORMAT_FLOAT_LE; - case AF_FORMAT_FLOAT_LE: - bits=32; - break; - case AF_FORMAT_S8: - format=AF_FORMAT_U8; - case AF_FORMAT_U8: - break; - case AF_FORMAT_AC3: - bits=16; - break; - default: - format=AF_FORMAT_S16_LE; - bits=16; - break; - } - - ao_data.outburst = 65536; - ao_data.buffersize= 2*65536; - ao_data.channels=channels; - ao_data.samplerate=rate; - ao_data.format=format; - ao_data.bps=channels*rate*(bits/8); - - wavhdr.riff = le2me_32(WAV_ID_RIFF); - wavhdr.wave = le2me_32(WAV_ID_WAVE); - wavhdr.fmt = le2me_32(WAV_ID_FMT); - wavhdr.fmt_length = le2me_32(16); - wavhdr.fmt_tag = le2me_16(format == AF_FORMAT_FLOAT_LE ? WAV_ID_FLOAT_PCM : WAV_ID_PCM); - wavhdr.channels = le2me_16(ao_data.channels); - wavhdr.sample_rate = le2me_32(ao_data.samplerate); - wavhdr.bytes_per_second = le2me_32(ao_data.bps); - wavhdr.bits = le2me_16(bits); - wavhdr.block_align = le2me_16(ao_data.channels * (bits / 8)); - - wavhdr.data = le2me_32(WAV_ID_DATA); - wavhdr.data_length=le2me_32(0x7ffff000); - wavhdr.file_length = wavhdr.data_length + sizeof(wavhdr) - 8; - - mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_PCM_FileInfo, ao_outputfilename, - (ao_pcm_waveheader?"WAVE":"RAW PCM"), rate, - (channels > 1) ? "Stereo" : "Mono", af_fmt2str_short(format)); - mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_PCM_HintInfo); - - fp = fopen(ao_outputfilename, "wb"); - if(fp) { - if(ao_pcm_waveheader){ /* Reserve space for wave header */ - fwrite(&wavhdr,sizeof(wavhdr),1,fp); - wavhdr.file_length=wavhdr.data_length=0; - } - return 1; - } - mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_PCM_CantOpenOutputFile, + int bits; + opt_t subopts[] = { + {"waveheader", OPT_ARG_BOOL, &ao_pcm_waveheader, NULL}, + {"file", OPT_ARG_MSTRZ, &ao_outputfilename, NULL}, + {"fast", OPT_ARG_BOOL, &fast, NULL}, + {NULL} + }; + // set defaults + ao_pcm_waveheader = 1; + + if (subopt_parse(ao_subdevice, subopts) != 0) { + return 0; + } + if (!ao_outputfilename){ + ao_outputfilename = + strdup(ao_pcm_waveheader?"audiodump.wav":"audiodump.pcm"); + } + + bits=8; + switch(format){ + case AF_FORMAT_S32_BE: + format=AF_FORMAT_S32_LE; + case AF_FORMAT_S32_LE: + bits=32; + break; + case AF_FORMAT_FLOAT_BE: + format=AF_FORMAT_FLOAT_LE; + case AF_FORMAT_FLOAT_LE: + bits=32; + break; + case AF_FORMAT_S8: + format=AF_FORMAT_U8; + case AF_FORMAT_U8: + break; + case AF_FORMAT_AC3: + bits=16; + break; + default: + format=AF_FORMAT_S16_LE; + bits=16; + break; + } + + ao_data.outburst = 65536; + ao_data.buffersize= 2*65536; + ao_data.channels=channels; + ao_data.samplerate=rate; + ao_data.format=format; + ao_data.bps=channels*rate*(bits/8); + + wavhdr.riff = le2me_32(WAV_ID_RIFF); + wavhdr.wave = le2me_32(WAV_ID_WAVE); + wavhdr.fmt = le2me_32(WAV_ID_FMT); + wavhdr.fmt_length = le2me_32(16); + wavhdr.fmt_tag = le2me_16(format == AF_FORMAT_FLOAT_LE ? WAV_ID_FLOAT_PCM : WAV_ID_PCM); + wavhdr.channels = le2me_16(ao_data.channels); + wavhdr.sample_rate = le2me_32(ao_data.samplerate); + wavhdr.bytes_per_second = le2me_32(ao_data.bps); + wavhdr.bits = le2me_16(bits); + wavhdr.block_align = le2me_16(ao_data.channels * (bits / 8)); + + wavhdr.data = le2me_32(WAV_ID_DATA); + wavhdr.data_length=le2me_32(0x7ffff000); + wavhdr.file_length = wavhdr.data_length + sizeof(wavhdr) - 8; + + mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_PCM_FileInfo, ao_outputfilename, + (ao_pcm_waveheader?"WAVE":"RAW PCM"), rate, + (channels > 1) ? "Stereo" : "Mono", af_fmt2str_short(format)); + mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_PCM_HintInfo); + + fp = fopen(ao_outputfilename, "wb"); + if(fp) { + if(ao_pcm_waveheader){ /* Reserve space for wave header */ + fwrite(&wavhdr,sizeof(wavhdr),1,fp); + } + return 1; + } + mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_PCM_CantOpenOutputFile, ao_outputfilename); - return 0; + return 0; } // close audio device static void uninit(int immed){ - - if(ao_pcm_waveheader && fseek(fp, 0, SEEK_SET) == 0){ /* Write wave header */ - wavhdr.file_length = wavhdr.data_length + sizeof(wavhdr) - 8; - wavhdr.file_length = le2me_32(wavhdr.file_length); - wavhdr.data_length = le2me_32(wavhdr.data_length); - fwrite(&wavhdr,sizeof(wavhdr),1,fp); - } - fclose(fp); - if (ao_outputfilename) - free(ao_outputfilename); - ao_outputfilename = NULL; + + if(ao_pcm_waveheader){ /* Rewrite wave header */ + if (fseek(fp, 0, SEEK_SET) != 0) + mp_msg(MSGT_AO, MSGL_ERR, "Could not seek to start, WAV size headers not updated!\n"); + else if (data_length > 0x7ffff000) + mp_msg(MSGT_AO, MSGL_ERR, "File larger than allowed for WAV files, may play truncated!\n"); + else { + wavhdr.file_length = data_length + sizeof(wavhdr) - 8; + wavhdr.file_length = le2me_32(wavhdr.file_length); + wavhdr.data_length = le2me_32(data_length); + fwrite(&wavhdr,sizeof(wavhdr),1,fp); + } + } + fclose(fp); + if (ao_outputfilename) + free(ao_outputfilename); + ao_outputfilename = NULL; } // stop playing and empty buffers (for seeking/pause) @@ -207,7 +213,7 @@ static void audio_resume(void) static int get_space(void){ if(vo_pts) - return ao_data.pts < vo_pts + fast * 30000 ? ao_data.outburst : 0; + return ao_data.pts < vo_pts + fast * 30000 ? ao_data.outburst : 0; return ao_data.outburst; } @@ -219,31 +225,31 @@ static int play(void* data,int len,int flags){ // let libaf to do the conversion... #if 0 //#ifdef WORDS_BIGENDIAN - if (ao_data.format == AFMT_S16_LE) { - unsigned short *buffer = (unsigned short *) data; - register int i; - for(i = 0; i < len/2; ++i) { - buffer[i] = le2me_16(buffer[i]); - } - } + if (ao_data.format == AFMT_S16_LE) { + unsigned short *buffer = (unsigned short *) data; + register int i; + for(i = 0; i < len/2; ++i) { + buffer[i] = le2me_16(buffer[i]); + } + } #endif - if (ao_data.channels == 6 || ao_data.channels == 5) { - int frame_size = le2me_16(wavhdr.bits) / 8; - len -= len % (frame_size * ao_data.channels); - reorder_channel_nch(data, AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT, - AF_CHANNEL_LAYOUT_WAVEEX_DEFAULT, - ao_data.channels, - len / frame_size, frame_size); - } - - //printf("PCM: Writing chunk!\n"); - fwrite(data,len,1,fp); - - if(ao_pcm_waveheader) - wavhdr.data_length += len; - - return len; + if (ao_data.channels == 6 || ao_data.channels == 5) { + int frame_size = le2me_16(wavhdr.bits) / 8; + len -= len % (frame_size * ao_data.channels); + reorder_channel_nch(data, AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT, + AF_CHANNEL_LAYOUT_WAVEEX_DEFAULT, + ao_data.channels, + len / frame_size, frame_size); + } + + //printf("PCM: Writing chunk!\n"); + fwrite(data,len,1,fp); + + if(ao_pcm_waveheader) + data_length += len; + + return len; } // return: delay in seconds between first and last sample in buffer |