fix the translator names list so that it conforms to lastname, firstname
[mplayer/glamo.git] / libao2 / ao_pcm.c
blob025c3b75ec82ab7d8ad00f66da643e37f37221dc
1 #include "config.h"
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
7 #include "bswap.h"
8 #include "subopt-helper.h"
9 #include "libaf/af_format.h"
10 #include "audio_out.h"
11 #include "audio_out_internal.h"
12 #include "mp_msg.h"
13 #include "help_mp.h"
16 static ao_info_t info =
18 "RAW PCM/WAVE file writer audio output",
19 "pcm",
20 "Atmosfear",
24 LIBAO_EXTERN(pcm)
26 extern int vo_pts;
28 static char *ao_outputfilename = NULL;
29 static int ao_pcm_waveheader = 1;
31 #define WAV_ID_RIFF 0x46464952 /* "RIFF" */
32 #define WAV_ID_WAVE 0x45564157 /* "WAVE" */
33 #define WAV_ID_FMT 0x20746d66 /* "fmt " */
34 #define WAV_ID_DATA 0x61746164 /* "data" */
35 #define WAV_ID_PCM 0x0001
37 struct WaveHeader
39 uint32_t riff;
40 uint32_t file_length;
41 uint32_t wave;
42 uint32_t fmt;
43 uint32_t fmt_length;
44 uint16_t fmt_tag;
45 uint16_t channels;
46 uint32_t sample_rate;
47 uint32_t bytes_per_second;
48 uint16_t block_align;
49 uint16_t bits;
50 uint32_t data;
51 uint32_t data_length;
54 /* init with default values */
55 static struct WaveHeader wavhdr = {
56 le2me_32(WAV_ID_RIFF),
57 /* same conventions than in sox/wav.c/wavwritehdr() */
58 0, //le2me_32(0x7ffff024),
59 le2me_32(WAV_ID_WAVE),
60 le2me_32(WAV_ID_FMT),
61 le2me_32(16),
62 le2me_16(WAV_ID_PCM),
63 le2me_16(2),
64 le2me_32(44100),
65 le2me_32(192000),
66 le2me_16(4),
67 le2me_16(16),
68 le2me_32(WAV_ID_DATA),
69 0, //le2me_32(0x7ffff000)
72 static FILE *fp = NULL;
74 // to set/get/query special features/parameters
75 static int control(int cmd,void *arg){
76 return -1;
79 // open & setup audio device
80 // return: 1=success 0=fail
81 static int init(int rate,int channels,int format,int flags){
82 int bits;
83 opt_t subopts[] = {
84 {"waveheader", OPT_ARG_BOOL, &ao_pcm_waveheader, NULL},
85 {"file", OPT_ARG_MSTRZ, &ao_outputfilename, NULL},
86 {NULL}
88 // set defaults
89 ao_pcm_waveheader = 1;
90 ao_outputfilename =
91 strdup((ao_pcm_waveheader)?"audiodump.wav":"audiodump.pcm");
92 if (subopt_parse(ao_subdevice, subopts) != 0) {
93 return 0;
96 /* bits is only equal to format if (format == 8) or (format == 16);
97 this means that the following "if" is a kludge and should
98 really be a switch to be correct in all cases */
100 bits=8;
101 switch(format){
102 case AF_FORMAT_S8:
103 format=AF_FORMAT_U8;
104 case AF_FORMAT_U8:
105 break;
106 default:
107 format=AF_FORMAT_S16_LE;
108 bits=16;
109 break;
112 ao_data.outburst = 65536;
113 ao_data.buffersize= 2*65536;
114 ao_data.channels=channels;
115 ao_data.samplerate=rate;
116 ao_data.format=format;
117 ao_data.bps=channels*rate*(bits/8);
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_length=le2me_32(0x7ffff000);
126 wavhdr.file_length = wavhdr.data_length + sizeof(wavhdr) - 8;
128 mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_PCM_FileInfo, ao_outputfilename,
129 (ao_pcm_waveheader?"WAVE":"RAW PCM"), rate,
130 (channels > 1) ? "Stereo" : "Mono", af_fmt2str_short(format));
131 mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_PCM_HintInfo);
133 fp = fopen(ao_outputfilename, "wb");
134 if(fp) {
135 if(ao_pcm_waveheader){ /* Reserve space for wave header */
136 fwrite(&wavhdr,sizeof(wavhdr),1,fp);
137 wavhdr.file_length=wavhdr.data_length=0;
139 return 1;
141 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_PCM_CantOpenOutputFile,
142 ao_outputfilename);
143 return 0;
146 // close audio device
147 static void uninit(int immed){
149 if(ao_pcm_waveheader && fseek(fp, 0, SEEK_SET) == 0){ /* Write wave header */
150 wavhdr.file_length = wavhdr.data_length + sizeof(wavhdr) - 8;
151 wavhdr.file_length = le2me_32(wavhdr.file_length);
152 wavhdr.data_length = le2me_32(wavhdr.data_length);
153 fwrite(&wavhdr,sizeof(wavhdr),1,fp);
155 fclose(fp);
156 if (ao_outputfilename)
157 free(ao_outputfilename);
158 ao_outputfilename = NULL;
161 // stop playing and empty buffers (for seeking/pause)
162 static void reset(){
166 // stop playing, keep buffers (for pause)
167 static void audio_pause()
169 // for now, just call reset();
170 reset();
173 // resume playing, after audio_pause()
174 static void audio_resume()
178 // return: how many bytes can be played without blocking
179 static int get_space(){
181 if(vo_pts)
182 return ao_data.pts < vo_pts ? ao_data.outburst : 0;
183 return ao_data.outburst;
186 // plays 'len' bytes of 'data'
187 // it should round it down to outburst*n
188 // return: number of bytes played
189 static int play(void* data,int len,int flags){
191 // let libaf to do the conversion...
192 #if 0
193 //#ifdef WORDS_BIGENDIAN
194 if (ao_data.format == AFMT_S16_LE) {
195 unsigned short *buffer = (unsigned short *) data;
196 register int i;
197 for(i = 0; i < len/2; ++i) {
198 buffer[i] = le2me_16(buffer[i]);
201 #endif
203 //printf("PCM: Writing chunk!\n");
204 fwrite(data,len,1,fp);
206 if(ao_pcm_waveheader)
207 wavhdr.data_length += len;
209 return len;
212 // return: delay in seconds between first and last sample in buffer
213 static float get_delay(){
215 return 0.0;