Applied the ogg123 patch and some minor fixes. Alex
[terminatorX.git] / src / tX_audiofile.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999, 2000  Alexander K├Ânig
4  
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9  
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  
19     File: tX_audiofile.cc
20  
21     Description: This implements the new audiofile class. Unlike earlier
22                  versions of terminatorX where wav_read.c was evilishly
23                  "#ifdef"ed to support multiple loading strategies this new
24                  design allows multiple load_*()-methods/strategies at
25                  the same time. (e.g. tx can now try to load a wavfile
26                  with the builtin routines and if that fails it'll try
27                  to load the file through sox (if available)).
28 */   
29
30 #include "tX_audiofile.h"
31
32 #include <string.h>
33 #include <malloc.h>
34 #include "wav_file.h"
35 #include "tX_loaddlg.h"
36
37 tx_audiofile :: tx_audiofile()
38 {
39         mem_type=TX_AUDIO_UNDEFINED;
40         file_type=TX_FILE_UNDEFINED;
41         file=NULL;
42         strcpy(filename,"");
43         mem=NULL;
44         no_samples=0;
45 }
46
47 void tx_audiofile :: figure_file_type()
48 {
49         char *ext;
50         
51         ext=strrchr(filename, (int) '.');
52         
53 //      puts(ext);
54         if (ext)
55         {
56                 if (strlen(ext) >3)
57                 {
58                         ext++;
59                         if (!strcasecmp("wav", ext)) file_type=TX_FILE_WAV;
60                         else if (!strncasecmp("mp", ext, 2)) file_type=TX_FILE_MPG123;
61                         else if (!strncasecmp("ogg", ext, 2)) file_type=TX_FILE_OGG123;
62                 }
63         }
64 }
65
66 int tx_audiofile :: load(char *p_file_name)
67 {
68         int load_err=TX_AUDIO_ERR_NOT_SUPPORTED;
69         
70         strcpy(filename, p_file_name);
71         
72         ld_set_progress(0);
73                 
74         figure_file_type();
75         
76 #ifdef USE_BUILTIN_WAV
77         if ((load_err) && (file_type==TX_FILE_WAV))
78                 load_err=load_wav();
79         
80         if (!load_err) return(load_err);        
81 #endif  
82
83 #ifdef USE_MPG123_INPUT
84         if ((load_err) && (file_type==TX_FILE_MPG123))
85         {
86                 load_err=load_mpg123();
87                 return(load_err);
88         }
89 #endif  
90
91 #ifdef USE_OGG123_INPUT
92         if ((load_err) && (file_type==TX_FILE_OGG123))
93         {
94                 load_err=load_ogg123();
95                 return(load_err);
96         }
97 #endif
98
99 #ifdef USE_SOX_INPUT
100         if (load_err)
101         {
102                 load_err=load_sox();
103         }
104 #endif  
105
106         return(load_err);
107 }
108
109  tx_audiofile :: ~tx_audiofile()
110  {
111
112         // clear mem
113
114         switch (mem_type)
115         {
116                 case TX_AUDIO_MMAP:
117                 {
118                         // unmap stuff
119                 }
120                 
121                 case TX_AUDIO_LOAD:
122                 {
123                         //munlock(void *mem, memsize);
124                         free(mem);
125                 }
126                 
127         }       
128
129         // clear file
130
131         if (file)
132         {
133                 if (mem_type==TX_AUDIO_MMAP)
134                 {
135                         // free mmap
136                 }
137         }
138         
139  }
140  
141 typedef struct tembpuff
142 {
143         char buffer[SOX_BLOCKSIZE];
144         ssize_t used;
145         void *next; 
146 } tempbuff;
147
148 static tempbuff *newbuff()
149 {
150         tempbuff *nwbf;
151         
152         nwbf=(tempbuff *) malloc(sizeof(tempbuff));
153         nwbf->next=NULL;
154         nwbf->used=0;
155         
156         return(nwbf);
157 }
158
159 #ifdef NEED_PIPED 
160
161 int tx_audiofile :: load_piped()
162 {
163         int16_t *data;
164         int16_t *p;
165         ssize_t allbytes=0;
166         ssize_t bytes=1;
167         int i;
168         tempbuff* start=NULL;
169         tempbuff* w=NULL;
170         tempbuff* newb=NULL;
171         
172         start=newbuff();
173         w=start;
174
175         mem_type=TX_AUDIO_LOAD;
176
177         ld_set_progress(0.5);
178                 
179         while (bytes)
180         {       
181                 bytes = fread(w->buffer, 1, SOX_BLOCKSIZE, file);
182                 w->used=bytes;
183 #ifdef BIG_ENDIAN_MACHINE
184                 swapbuffer((int16_t *) w->buffer, bytes/sizeof(int16_t));
185 #endif          
186                 
187                 if (bytes)
188                 {
189                         newb=newbuff();
190                         if (!newb) return (TX_AUDIO_ERR_ALLOC);
191                         w->next=newb;
192                         w=newb;
193                 }                               
194
195 #ifdef BIG_ENDIAN_MACHINE
196                 //if (!wav_in.has_host_order) swapbuffer(p, bytes/sizeof(int16_t));
197 #endif          
198                 allbytes+=bytes;                        
199         }
200         
201         pclose(file); file=NULL;
202         
203         if (!allbytes)  // Nothing read from pipe -> error
204         {
205                 free(start);
206                 return (TX_AUDIO_ERR_PIPE_READ);
207         }
208
209         no_samples=allbytes/sizeof(int16_t);
210         memsize=allbytes;
211         data = (int16_t *) malloc (memsize);
212         
213         if (!data)
214         {
215                 w=start;
216                 while (w)
217                 {
218                         newb=(tempbuff*)w->next;
219                         free(w);
220                         w=newb;
221                 }
222                 return(TX_AUDIO_ERR_ALLOC);
223         }
224         
225         w=start;
226         p=data;
227
228         bytes=0;
229         
230         while(w)
231         {
232                 memcpy(p, w->buffer, w->used);
233                 bytes+=w->used;
234                 newb=(tempbuff*) w->next;
235                 free(w);
236                 w=newb;
237                 
238                 ld_set_progress(0.5 + 0.5*((gfloat) bytes)/((gfloat) allbytes));
239                 
240                 p+=(ssize_t) SOX_BLOCKSIZE/sizeof(int16_t);
241         }
242
243         mem=data;
244         return (TX_AUDIO_SUCCESS);
245 }
246
247 #endif
248         
249 #ifdef USE_SOX_INPUT
250 int tx_audiofile :: load_sox()
251 {
252         char command[PATH_MAX*2];
253
254         sprintf(command, SOX_STR, filename);
255         file = popen(command, "r");
256         
257         if (!file) return TX_AUDIO_ERR_SOX;
258         
259         return load_piped();
260         
261 }
262 #endif  
263
264 #ifdef USE_MPG123_INPUT
265 int tx_audiofile :: load_mpg123()
266 {
267         char command[PATH_MAX*2];
268         
269         sprintf(command, MPG123_STR, filename);
270         file = popen(command, "r");
271         
272         if (!file) return TX_AUDIO_ERR_MPG123;
273         
274         return load_piped();    
275 }
276 #endif  
277
278 #ifdef USE_OGG123_INPUT
279 int tx_audiofile :: load_ogg123()
280 {
281         char command[PATH_MAX*2];
282
283         sprintf(command, OGG123_STR, filename);
284         file = popen(command, "r");
285
286         if (!file) return TX_AUDIO_ERR_OGG123;
287
288         return load_piped();
289 }
290 #endif
291
292 #ifdef USE_BUILTIN_WAV
293 #define min(a,b) ((a) < (b) ? (a) : (b))
294 int tx_audiofile :: load_wav()
295 {
296         wav_sig wav_in;
297         int16_t *data;
298         int16_t *p;
299         ssize_t allbytes=0;
300         ssize_t bytes=0;
301         int i;
302
303         mem_type=TX_AUDIO_LOAD;
304         
305         if (!init_wav_read(filename, &wav_in))
306         {
307                 return(TX_AUDIO_ERR_WAV_NOTFOUND);
308         }
309
310 #ifdef USE_CONSOLE
311         printf("Loading: %s\n", filename);
312         if (parms.verbose) printf("File: %i Bytes Data, %i Bit Depth, %i Hz Samplerate.\n", wav_in.len, wav_in.depth, wav_in.srate);    
313 #endif  
314
315         if (wav_in.depth != 16)
316         {
317                 return(TX_AUDIO_ERR_NOT_16BIT);
318         }
319
320         if (wav_in.chans != 1)
321         {
322                 return(TX_AUDIO_ERR_NOT_MONO);
323         }
324
325 #ifdef USE_CONSOLE      
326         if (wav_in.srate != 44100) 
327         {
328                 puts("[load_wav] Warning: Wave-File was not recorded at 44.100 Hz!");
329         }
330         if (wav_in.blkalign != 2)
331         {
332                 printf("[load_wav] Warning: Unexpected block alignment: %i.\n", wav_in.blkalign);
333         }
334 #endif
335
336         memsize=wav_in.len;
337         data = (int16_t *) malloc (memsize);
338                 
339         if (!data)
340         {
341                 return(TX_AUDIO_ERR_ALLOC);
342         }
343
344         p=data;
345         
346         while (wav_in.len>allbytes)
347         {       
348                 bytes = fread(p, 1, min(1024, wav_in.len-allbytes), wav_in.handle);
349
350 #ifdef BIG_ENDIAN_MACHINE
351 //              if (!wav_in.has_host_order) swapbuffer(p, bytes/sizeof(int16_t));
352 #endif          
353                 if (bytes<=0)
354                 {
355                         free(data);
356                         //wav_progress_update(0);
357                       return (TX_AUDIO_ERR_WAV_READ);
358                 }
359                 allbytes+=bytes;
360                 
361                 ld_set_progress((float) allbytes/(float)wav_in.len);
362                 
363                 p+=(ssize_t) bytes/sizeof(int16_t);
364         }
365         
366         wav_close(wav_in.handle);
367
368         mem=data;
369         no_samples=memsize/sizeof(int16_t);
370         
371 //      printf("WAV: data: %08x, size %i, len: %i\n", data, memsize, no_samples);       
372
373         return (TX_AUDIO_SUCCESS);
374 }
375 #endif