7 #include "libavutil/common.h"
9 #include "subopt-helper.h"
10 #include "libaf/af_format.h"
11 #include "libaf/reorder_ch.h"
12 #include "audio_out.h"
13 #include "audio_out_internal.h"
18 static ao_info_t info
=
20 "RAW PCM/WAVE file writer audio output",
30 static char *ao_outputfilename
= NULL
;
31 static int ao_pcm_waveheader
= 1;
34 #define WAV_ID_RIFF 0x46464952 /* "RIFF" */
35 #define WAV_ID_WAVE 0x45564157 /* "WAVE" */
36 #define WAV_ID_FMT 0x20746d66 /* "fmt " */
37 #define WAV_ID_DATA 0x61746164 /* "data" */
38 #define WAV_ID_PCM 0x0001
50 uint32_t bytes_per_second
;
57 /* init with default values */
58 static struct WaveHeader wavhdr
;
60 static FILE *fp
= NULL
;
62 // to set/get/query special features/parameters
63 static int control(int cmd
,void *arg
){
67 // open & setup audio device
68 // return: 1=success 0=fail
69 static int init(int rate
,int channels
,int format
,int flags
){
72 {"waveheader", OPT_ARG_BOOL
, &ao_pcm_waveheader
, NULL
},
73 {"file", OPT_ARG_MSTRZ
, &ao_outputfilename
, NULL
},
74 {"fast", OPT_ARG_BOOL
, &fast
, NULL
},
78 ao_pcm_waveheader
= 1;
80 if (subopt_parse(ao_subdevice
, subopts
) != 0) {
83 if (!ao_outputfilename
){
85 strdup(ao_pcm_waveheader
?"audiodump.wav":"audiodump.pcm");
88 /* bits is only equal to format if (format == 8) or (format == 16);
89 this means that the following "if" is a kludge and should
90 really be a switch to be correct in all cases */
102 format
=AF_FORMAT_S16_LE
;
107 ao_data
.outburst
= 65536;
108 ao_data
.buffersize
= 2*65536;
109 ao_data
.channels
=channels
;
110 ao_data
.samplerate
=rate
;
111 ao_data
.format
=format
;
112 ao_data
.bps
=channels
*rate
*(bits
/8);
114 wavhdr
.riff
= le2me_32(WAV_ID_RIFF
);
115 wavhdr
.wave
= le2me_32(WAV_ID_WAVE
);
116 wavhdr
.fmt
= le2me_32(WAV_ID_FMT
);
117 wavhdr
.fmt_length
= le2me_32(16);
118 wavhdr
.fmt_tag
= le2me_16(WAV_ID_PCM
);
119 wavhdr
.channels
= le2me_16(ao_data
.channels
);
120 wavhdr
.sample_rate
= le2me_32(ao_data
.samplerate
);
121 wavhdr
.bytes_per_second
= le2me_32(ao_data
.bps
);
122 wavhdr
.bits
= le2me_16(bits
);
123 wavhdr
.block_align
= le2me_16(ao_data
.channels
* (bits
/ 8));
125 wavhdr
.data
= le2me_32(WAV_ID_DATA
);
126 wavhdr
.data_length
=le2me_32(0x7ffff000);
127 wavhdr
.file_length
= wavhdr
.data_length
+ sizeof(wavhdr
) - 8;
129 mp_msg(MSGT_AO
, MSGL_INFO
, MSGTR_AO_PCM_FileInfo
, ao_outputfilename
,
130 (ao_pcm_waveheader
?"WAVE":"RAW PCM"), rate
,
131 (channels
> 1) ? "Stereo" : "Mono", af_fmt2str_short(format
));
132 mp_msg(MSGT_AO
, MSGL_INFO
, MSGTR_AO_PCM_HintInfo
);
134 fp
= fopen(ao_outputfilename
, "wb");
136 if(ao_pcm_waveheader
){ /* Reserve space for wave header */
137 fwrite(&wavhdr
,sizeof(wavhdr
),1,fp
);
138 wavhdr
.file_length
=wavhdr
.data_length
=0;
142 mp_msg(MSGT_AO
, MSGL_ERR
, MSGTR_AO_PCM_CantOpenOutputFile
,
147 // close audio device
148 static void uninit(int immed
){
150 if(ao_pcm_waveheader
&& fseek(fp
, 0, SEEK_SET
) == 0){ /* Write wave header */
151 wavhdr
.file_length
= wavhdr
.data_length
+ sizeof(wavhdr
) - 8;
152 wavhdr
.file_length
= le2me_32(wavhdr
.file_length
);
153 wavhdr
.data_length
= le2me_32(wavhdr
.data_length
);
154 fwrite(&wavhdr
,sizeof(wavhdr
),1,fp
);
157 if (ao_outputfilename
)
158 free(ao_outputfilename
);
159 ao_outputfilename
= NULL
;
162 // stop playing and empty buffers (for seeking/pause)
163 static void reset(void){
167 // stop playing, keep buffers (for pause)
168 static void audio_pause(void)
170 // for now, just call reset();
174 // resume playing, after audio_pause()
175 static void audio_resume(void)
179 // return: how many bytes can be played without blocking
180 static int get_space(void){
183 return ao_data
.pts
< vo_pts
+ fast
* 30000 ? ao_data
.outburst
: 0;
184 return ao_data
.outburst
;
187 // plays 'len' bytes of 'data'
188 // it should round it down to outburst*n
189 // return: number of bytes played
190 static int play(void* data
,int len
,int flags
){
192 // let libaf to do the conversion...
194 //#ifdef WORDS_BIGENDIAN
195 if (ao_data
.format
== AFMT_S16_LE
) {
196 unsigned short *buffer
= (unsigned short *) data
;
198 for(i
= 0; i
< len
/2; ++i
) {
199 buffer
[i
] = le2me_16(buffer
[i
]);
204 if (ao_data
.channels
== 6 || ao_data
.channels
== 5) {
205 int frame_size
= le2me_16(wavhdr
.bits
) / 8;
206 len
-= len
% (frame_size
* ao_data
.channels
);
207 reorder_channel_nch(data
, AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT
,
208 AF_CHANNEL_LAYOUT_WAVEEX_DEFAULT
,
210 len
/ frame_size
, frame_size
);
213 //printf("PCM: Writing chunk!\n");
214 fwrite(data
,len
,1,fp
);
216 if(ao_pcm_waveheader
)
217 wavhdr
.data_length
+= len
;
222 // return: delay in seconds between first and last sample in buffer
223 static float get_delay(void){