Alex: Added the new sources for terminatorX 3.5
[terminatorX.git] / src / tX_wavfunc.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999  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_wavfunc.c
20  
21     Description: Contains routines for loading the loop and scratch
22                  files and allocating the record buffer.
23 */    
24
25 #include "tX_types.h"
26 #include "tX_mastergui.h"
27 #include "wav_file.h"
28 #include "tX_wavfunc.h"
29 #include "tX_global.h"
30 #include <stdio.h>
31 #ifndef WIN32
32 #include <unistd.h>
33 #endif
34 #include <malloc.h>
35
36 #define min(a,b) ((a) < (b) ? (a) : (b))
37
38 #define SOX_BLOCKSIZE 32000
39
40 #ifdef USE_SOX_INPUT
41 typedef struct
42 {
43         char buffer[SOX_BLOCKSIZE];
44         ssize_t used;
45         void *next; 
46 } tempbuff;
47
48 tempbuff *newbuff()
49 {
50         tempbuff *nwbf;
51         
52         nwbf=(tempbuff *) malloc(sizeof(tempbuff));
53         nwbf->next=NULL;
54         nwbf->used=0;
55         
56         return(nwbf);
57 }
58 #endif
59
60 int load_wav(char *name, int16_t **data_ptr, unsigned int *size)
61 {
62         wav_sig wav_in;
63         int16_t *data;
64         int16_t *p;
65         ssize_t allbytes=0;
66         ssize_t bytes=0;
67         int i;
68 #ifdef USE_SOX_INPUT
69         tempbuff* start=NULL;
70         tempbuff* w=NULL;
71         tempbuff* newb=NULL;
72         
73 //      int blink=0;
74 //      int buffsum=0;
75 #endif  
76         
77         if (!init_wav_read(name, &wav_in))
78         {
79 #ifdef USE_CONSOLE
80                 printf("[load_wav] Error. Couldn't open \"%s\".\n", name);              
81 #endif  
82                 return(LW_ERROR_FILE_NOT_FOUND);
83         }
84
85 #ifdef USE_CONSOLE
86         printf("Loading: %s\n", name);
87         if (parms.verbose) printf("File: %i Bytes Data, %i Bit Depth, %i Hz Samplerate.\n", wav_in.len, wav_in.depth, wav_in.srate);    
88 #endif  
89
90 #ifndef USE_SOX_INPUT
91         
92         if (wav_in.depth != 16)
93         {
94 #ifdef USE_CONSOLE
95                 puts("[load_wav] Error: Wave-File is not 16 Bit. Fatal. Giving up.");           
96 #endif          
97                 return(LW_ERROR_FILE_NOT_16BIT);
98         }
99
100         if (wav_in.chans != 1)
101         {
102 #ifdef USE_CONSOLE      
103                 puts("[load_wav] Error: Wave-File is not Mono. Fatal. Giving up.");
104 #endif
105                 return(LW_ERROR_FILE_NOT_MONO);
106         }
107
108 #ifdef USE_CONSOLE      
109         if (wav_in.srate != 44100) 
110         {
111                 puts("[load_wav] Warning: Wave-File was not recorded at 44.100 Hz!");
112         }
113         if (wav_in.blkalign != 2)
114         {
115                 printf("[load_wav] Warning: Unexpected block alignment: %i.\n", wav_in.blkalign);
116         }
117 #endif
118
119         *size=wav_in.len;
120         data = (int16_t *) malloc (*size);
121                 
122         if (!data)
123         {
124 #ifdef USE_CONSOLE
125                 puts("[load_wav] Error: Failed to allocate sample memory. Fatal. Giving up.");
126 #endif  
127                 return(LW_ERROR_ALLOC);
128         }
129 #endif
130
131 #ifdef USE_SOX_INPUT
132         bytes=1;                
133         
134         start=newbuff();
135         w=start;
136         
137         wav_progress_update(0.5); /* Yeehha! A realistic Progessbar ;) */
138         
139         while (bytes)
140 #else
141         p=data;
142         
143         while (wav_in.len>allbytes)
144 #endif  
145         {       
146 #ifdef USE_SOX_INPUT    
147                 bytes = fread(w->buffer, 1, SOX_BLOCKSIZE, wav_in.handle);
148                 w->used=bytes;
149                 
150 /*              buffsum++;
151                 if (buffsum>5)
152                 {
153                         if (blink)
154                         {
155                                 blink=0;
156                                 wav_progress_update(0.5);
157                         }
158                         else
159                         {
160                                 blink=1;
161                                 wav_progress_update(0.25);
162                         }
163                         buffsum=0;
164                 }*/
165                 
166 #ifdef BIG_ENDIAN_MACHINE
167                 swapbuffer(w->buffer, bytes/sizeof(int16_t));
168 #endif          
169                 
170                 if (bytes)
171                 {
172                         newb=newbuff();
173                         if (!newb) return (LW_ERROR_ALLOC);
174                         w->next=newb;
175                         w=newb;
176                 }                               
177 #else
178         
179                 bytes = fread(p, 1, min(1024, wav_in.len-allbytes), wav_in.handle);
180
181 #ifdef BIG_ENDIAN_MACHINE
182                 if (!wav_in.has_host_order) swapbuffer(p, bytes/sizeof(int16_t));
183 #endif          
184                 
185                 if (bytes<=0)
186                 {
187 #ifdef USE_CONSOLE
188                        puts("[load_wav] Error: Failed to read Wave-Data (Corrupt?). Fatal. Giving up.");
189                        if(bytes<0) perror("terminatorX");
190 #endif          
191                         free(data);
192                         wav_progress_update(0);
193                       return (LW_ERROR_READ);
194                 }
195                                 
196 #endif          // USE_SOX_INPUT
197
198                 allbytes+=bytes;
199                 
200 #ifndef USE_SOX_INPUT
201                 wav_progress_update(((gfloat) allbytes)/((gfloat) wav_in.len));
202                 
203                 p+=(ssize_t) bytes/sizeof(int16_t);
204 #endif          
205         }
206         
207         wav_close(wav_in.handle);
208
209 #ifdef USE_SOX_INPUT
210         if (!allbytes)  // Nothing read from pipe -> error
211         {
212                 free(start);
213                 return (LW_ERROR_READ);
214         }
215 #endif
216
217 #ifdef USE_CONSOLE
218         if (parms.verbose) printf("Read: %i Bytes of Wave-Data.\n", allbytes);
219 #endif  
220
221 #ifdef USE_SOX_INPUT
222         *size=allbytes;
223         data = (int16_t *) malloc (*size);
224         
225         if (!data)
226         {
227                 return(LW_ERROR_ALLOC);
228         }
229         
230         w=start;
231         p=data;
232
233         bytes=0;
234         
235         while(w)
236         {
237                 memcpy(p, w->buffer, w->used);
238                 bytes+=w->used;
239                 newb=(tempbuff*) w->next;
240                 free(w);
241                 w=newb;
242                 
243                 wav_progress_update(0.5 + 0.5*((gfloat) bytes)/((gfloat) allbytes));
244                 
245                 p+=(ssize_t) SOX_BLOCKSIZE/sizeof(int16_t);
246         }
247
248 #endif
249         wav_progress_update(0);
250
251         *data_ptr=data;
252
253         return (LW_NO_ERROR);
254 }
255
256 int malloc_recbuffer()
257 {
258         if (globals.rec_buffer) free(globals.rec_buffer);
259         globals.rec_buffer=(int16_t*) malloc((ssize_t) globals.rec_size);
260         if (globals.rec_buffer!=NULL) return(0);
261         else return(1);
262 }