Diffstat (limited to 'core/multimedia/opieplayer/wavplugin/wavplugin.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/wavplugin/wavplugin.cpp | 261 |
1 files changed, 134 insertions, 127 deletions
diff --git a/core/multimedia/opieplayer/wavplugin/wavplugin.cpp b/core/multimedia/opieplayer/wavplugin/wavplugin.cpp index a6bd974..7f63b3b 100644 --- a/core/multimedia/opieplayer/wavplugin/wavplugin.cpp +++ b/core/multimedia/opieplayer/wavplugin/wavplugin.cpp | |||
@@ -14,22 +14,24 @@ | |||
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
15 | ** | 15 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 16 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 17 | ** not clear to you. |
18 | ** | 18 | ** |
19 | **********************************************************************/ | 19 | **********************************************************************/ |
20 | // L.J.Potter added changes Fri 02-15-2002 | ||
21 | |||
20 | #include <stdio.h> | 22 | #include <stdio.h> |
21 | #include <stdarg.h> | 23 | #include <stdarg.h> |
22 | #include <stdlib.h> | 24 | #include <stdlib.h> |
23 | #include <errno.h> | 25 | #include <errno.h> |
24 | #include <unistd.h> | 26 | #include <unistd.h> |
25 | #include <qfile.h> | 27 | #include <qfile.h> |
26 | #include "wavplugin.h" | 28 | #include "wavplugin.h" |
27 | 29 | ||
28 | 30 | ||
29 | //#define debugMsg(a) qDebug(a) | 31 | //#define debugMsg(a) qDebug(a) |
30 | #define debugMsg(a) | 32 | #define debugMsg(a) |
31 | 33 | ||
32 | 34 | ||
33 | struct RiffChunk { | 35 | struct RiffChunk { |
34 | char id[4]; | 36 | char id[4]; |
35 | Q_UINT32 size; | 37 | Q_UINT32 size; |
@@ -44,13 +46,13 @@ struct ChunkData { | |||
44 | Q_INT32 avgBytesPerSec; | 46 | Q_INT32 avgBytesPerSec; |
45 | Q_INT16 blockAlign; | 47 | Q_INT16 blockAlign; |
46 | Q_INT16 wBitsPerSample; | 48 | Q_INT16 wBitsPerSample; |
47 | }; | 49 | }; |
48 | 50 | ||
49 | 51 | ||
50 | const int sound_buffer_size = 4096; | 52 | const int sound_buffer_size = 512; // 4096; // you got to be kidding right? |
51 | 53 | ||
52 | 54 | ||
53 | class WavPluginData { | 55 | class WavPluginData { |
54 | public: | 56 | public: |
55 | QFile *input; | 57 | QFile *input; |
56 | 58 | ||
@@ -60,136 +62,136 @@ public: | |||
60 | uchar data[sound_buffer_size+32]; // +32 to handle badly aligned input data | 62 | uchar data[sound_buffer_size+32]; // +32 to handle badly aligned input data |
61 | int out,max; | 63 | int out,max; |
62 | int samples_due; | 64 | int samples_due; |
63 | int samples; | 65 | int samples; |
64 | 66 | ||
65 | WavPluginData() { | 67 | WavPluginData() { |
66 | max = out = sound_buffer_size; | 68 | max = out = sound_buffer_size; |
67 | wavedata_remaining = 0; | 69 | wavedata_remaining = 0; |
68 | samples_due = 0; | 70 | samples_due = 0; |
69 | samples = -1; | 71 | samples = -1; |
70 | } | 72 | } |
71 | 73 | ||
72 | // expands out samples to the frequency of 44kHz | 74 | // expands out samples to the frequency of 44kHz |
73 | bool add( short *output, long count, long& done, bool stereo ) | 75 | bool add( short *output, long count, long& done, bool stereo ) |
74 | { | 76 | { |
75 | done = 0; | 77 | done = 0; |
78 | qApp->processEvents(); | ||
76 | 79 | ||
77 | if ( input == 0 ) { | 80 | if ( input == 0 ) { |
78 | qDebug("no input"); | 81 | qDebug("no input"); |
79 | return FALSE; | 82 | return FALSE; |
80 | } | 83 | } |
81 | 84 | ||
82 | while ( count ) { | 85 | while ( count ) { |
83 | int l,r; | 86 | int l,r; |
84 | if ( getSample(l, r) == FALSE ) { | 87 | if ( getSample(l, r) == FALSE ) { |
85 | qDebug("didn't get sample"); | 88 | qDebug("didn't get sample"); |
86 | return FALSE; | 89 | return FALSE; |
87 | } | 90 | } |
88 | samples_due += 44100; | 91 | samples_due += chunkdata.samplesPerSec; |
89 | while ( count && (samples_due > chunkdata.samplesPerSec) ) { | 92 | while ( count && (samples_due > chunkdata.samplesPerSec) ) { |
90 | *output++ = l; | 93 | *output++ = l; |
91 | if ( stereo ) | 94 | if ( stereo ) |
92 | *output++ = r; | 95 | *output++ = r; |
93 | samples_due -= chunkdata.samplesPerSec; | 96 | samples_due -= chunkdata.samplesPerSec; |
94 | count--; | 97 | count--; |
95 | done++; | 98 | done++; |
96 | } | 99 | } |
97 | } | 100 | } |
98 | |||
99 | return TRUE; | 101 | return TRUE; |
100 | } | 102 | } |
101 | 103 | ||
102 | bool initialise() { | 104 | bool initialise() { |
103 | if ( input == 0 ) | 105 | if ( input == 0 ) |
104 | return FALSE; | 106 | return FALSE; |
105 | 107 | ||
106 | wavedata_remaining = -1; | 108 | wavedata_remaining = -1; |
107 | 109 | ||
108 | while ( wavedata_remaining == -1 ) { | 110 | while ( wavedata_remaining == -1 ) { |
109 | // Keep reading chunks... | 111 | // Keep reading chunks... |
110 | const int n = sizeof(chunk) - sizeof(chunk.data); | 112 | const int n = sizeof(chunk) - sizeof(chunk.data); |
111 | int t = input->readBlock( (char*)&chunk, n ); | 113 | int t = input->readBlock( (char*)&chunk, n ); |
112 | if ( t != n ) { | 114 | if ( t != n ) { |
113 | if ( t == -1 ) | 115 | if ( t == -1 ) |
114 | return FALSE; | 116 | return FALSE; |
115 | return TRUE; | 117 | return TRUE; |
116 | } | 118 | } |
117 | if ( qstrncmp(chunk.id,"data",4) == 0 ) { | 119 | if ( qstrncmp(chunk.id,"data",4) == 0 ) { |
118 | samples = wavedata_remaining = chunk.size; | 120 | samples = wavedata_remaining = chunk.size; |
119 | } else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) { | 121 | } else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) { |
120 | char d[4]; | 122 | char d[4]; |
121 | if ( input->readBlock(d,4) != 4 ) { | 123 | if ( input->readBlock(d,4) != 4 ) { |
122 | return FALSE; | 124 | return FALSE; |
123 | } | 125 | } |
124 | if ( qstrncmp(d,"WAVE",4) != 0 ) { | 126 | if ( qstrncmp(d,"WAVE",4) != 0 ) { |
125 | // skip | 127 | // skip |
126 | if ( chunk.size > 1000000000 || !input->at(input->at()+chunk.size-4) ) { | 128 | if ( chunk.size > 1000000000 || !input->at(input->at()+chunk.size-4) ) { |
127 | return FALSE; | 129 | return FALSE; |
128 | } | 130 | } |
129 | } | 131 | } |
130 | } else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) { | 132 | } else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) { |
131 | if ( input->readBlock((char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) ) { | 133 | if ( input->readBlock((char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) ) { |
132 | return FALSE; | 134 | return FALSE; |
133 | } | 135 | } |
134 | #define WAVE_FORMAT_PCM 1 | 136 | #define WAVE_FORMAT_PCM 1 |
135 | if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) { | 137 | if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) { |
136 | qDebug("WAV file: UNSUPPORTED FORMAT %d",chunkdata.formatTag); | 138 | qDebug("WAV file: UNSUPPORTED FORMAT %d",chunkdata.formatTag); |
137 | return FALSE; | 139 | return FALSE; |
138 | } | 140 | } |
139 | } else { | 141 | } else { |
140 | // ignored chunk | 142 | // ignored chunk |
141 | if ( chunk.size > 1000000000 || !input->at(input->at()+chunk.size) ) { | 143 | if ( chunk.size > 1000000000 || !input->at(input->at()+chunk.size) ) { |
142 | return FALSE; | 144 | return FALSE; |
143 | } | 145 | } |
144 | } | 146 | } |
145 | } // while | 147 | } // while |
146 | 148 | qDebug("bits %d", chunkdata.wBitsPerSample); | |
147 | return TRUE; | 149 | return TRUE; |
148 | } | 150 | } |
149 | 151 | ||
150 | 152 | ||
151 | // gets a sample from the file | 153 | // gets a sample from the file |
152 | bool getSample(int& l, int& r) | 154 | bool getSample(int& l, int& r) |
153 | { | 155 | { |
154 | l = r = 0; | 156 | l = r = 0; |
155 | 157 | ||
156 | if ( input == 0 ) | 158 | if ( input == 0 ) |
157 | return FALSE; | 159 | return FALSE; |
158 | 160 | ||
159 | if ( (wavedata_remaining < 0) || !max ) | 161 | if ( (wavedata_remaining < 0) || !max ) |
160 | return FALSE; | 162 | return FALSE; |
161 | 163 | ||
162 | if ( out >= max ) { | 164 | if ( out >= max ) { |
163 | max = input->readBlock( (char*)data, (uint)QMIN(sound_buffer_size,wavedata_remaining) ); | 165 | max = input->readBlock( (char*)data, (uint)QMIN(sound_buffer_size,wavedata_remaining) ); |
164 | 166 | ||
165 | wavedata_remaining -= max; | 167 | wavedata_remaining -= max; |
166 | 168 | ||
167 | out = 0; | 169 | out = 0; |
168 | if ( max <= 0 ) { | 170 | if ( max <= 0 ) { |
169 | max = 0; | 171 | max = 0; |
170 | return TRUE; | 172 | return TRUE; |
171 | } | 173 | } |
172 | } | 174 | } |
173 | if ( chunkdata.wBitsPerSample == 8 ) { | 175 | if ( chunkdata.wBitsPerSample == 8 ) { |
174 | l = (data[out++] - 128) * 128; | 176 | l = (data[out++] - 128) * 128; |
175 | } else { | 177 | } else { |
176 | l = ((short*)data)[out/2]; | 178 | l = ((short*)data)[out/2]; |
177 | out += 2; | 179 | out += 2; |
178 | } | 180 | } |
179 | if ( chunkdata.channels == 1 ) { | 181 | if ( chunkdata.channels == 1 ) { |
180 | r = l; | 182 | r = l; |
181 | } else { | 183 | } else { |
182 | if ( chunkdata.wBitsPerSample == 8 ) { | 184 | if ( chunkdata.wBitsPerSample == 8 ) { |
183 | r = (data[out++] - 128) * 128; | 185 | r = (data[out++] - 128) * 128; |
184 | } else { | 186 | } else { |
185 | r = ((short*)data)[out/2]; | 187 | r = ((short*)data)[out/2]; |
186 | out += 2; | 188 | out += 2; |
187 | } | 189 | } |
188 | } | 190 | } |
189 | return TRUE; | 191 | return TRUE; |
190 | } // getSample | 192 | } // getSample |
191 | 193 | ||
192 | }; | 194 | }; |
193 | 195 | ||
194 | 196 | ||
195 | WavPlugin::WavPlugin() { | 197 | WavPlugin::WavPlugin() { |
@@ -202,100 +204,100 @@ WavPlugin::~WavPlugin() { | |||
202 | close(); | 204 | close(); |
203 | delete d; | 205 | delete d; |
204 | } | 206 | } |
205 | 207 | ||
206 | 208 | ||
207 | bool WavPlugin::isFileSupported( const QString& path ) { | 209 | bool WavPlugin::isFileSupported( const QString& path ) { |
208 | debugMsg( "WavPlugin::isFileSupported" ); | 210 | // qDebug( "WavPlugin::isFileSupported" ); |
209 | 211 | ||
210 | char *ext = strrchr( path.latin1(), '.' ); | 212 | char *ext = strrchr( path.latin1(), '.' ); |
211 | 213 | ||
212 | // Test file extension | 214 | // Test file extension |
213 | if ( ext ) { | 215 | if ( ext ) { |
214 | if ( strncasecmp(ext, ".raw", 4) == 0 ) | 216 | if ( strncasecmp(ext, ".raw", 4) == 0 ) |
215 | return TRUE; | 217 | return TRUE; |
216 | if ( strncasecmp(ext, ".wav", 4) == 0 ) | 218 | if ( strncasecmp(ext, ".wav", 4) == 0 ) |
217 | return TRUE; | 219 | return TRUE; |
218 | if ( strncasecmp(ext, ".wave", 4) == 0 ) | 220 | if ( strncasecmp(ext, ".wave", 4) == 0 ) |
219 | return TRUE; | 221 | return TRUE; |
220 | } | 222 | } |
221 | 223 | ||
222 | return FALSE; | 224 | return FALSE; |
223 | } | 225 | } |
224 | 226 | ||
225 | 227 | ||
226 | bool WavPlugin::open( const QString& path ) { | 228 | bool WavPlugin::open( const QString& path ) { |
227 | debugMsg( "WavPlugin::open" ); | 229 | // qDebug( "WavPlugin::open" ); |
228 | 230 | ||
229 | d->max = d->out = sound_buffer_size; | 231 | d->max = d->out = sound_buffer_size; |
230 | d->wavedata_remaining = 0; | 232 | d->wavedata_remaining = 0; |
231 | d->samples_due = 0; | 233 | d->samples_due = 0; |
232 | 234 | ||
233 | d->input = new QFile( path ); | 235 | d->input = new QFile( path ); |
234 | if ( d->input->open(IO_ReadOnly) == FALSE ) { | 236 | if ( d->input->open(IO_ReadOnly) == FALSE ) { |
235 | qDebug("couldn't open file"); | 237 | qDebug("couldn't open file"); |
236 | delete d->input; | 238 | delete d->input; |
237 | d->input = 0; | 239 | d->input = 0; |
238 | return FALSE; | 240 | return FALSE; |
239 | } | 241 | } |
240 | 242 | ||
241 | d->initialise(); | 243 | d->initialise(); |
242 | 244 | ||
243 | return TRUE; | 245 | return TRUE; |
244 | } | 246 | } |
245 | 247 | ||
246 | 248 | ||
247 | bool WavPlugin::close() { | 249 | bool WavPlugin::close() { |
248 | debugMsg( "WavPlugin::close" ); | 250 | // qDebug( "WavPlugin::close" ); |
249 | 251 | ||
250 | d->input->close(); | 252 | d->input->close(); |
251 | delete d->input; | 253 | delete d->input; |
252 | d->input = 0; | 254 | d->input = 0; |
253 | return TRUE; | 255 | return TRUE; |
254 | } | 256 | } |
255 | 257 | ||
256 | 258 | ||
257 | bool WavPlugin::isOpen() { | 259 | bool WavPlugin::isOpen() { |
258 | debugMsg( "WavPlugin::isOpen" ); | 260 | // qDebug( "WavPlugin::isOpen" ); |
259 | return ( d->input != 0 ); | 261 | return ( d->input != 0 ); |
260 | } | 262 | } |
261 | 263 | ||
262 | 264 | ||
263 | int WavPlugin::audioStreams() { | 265 | int WavPlugin::audioStreams() { |
264 | debugMsg( "WavPlugin::audioStreams" ); | 266 | // qDebug( "WavPlugin::audioStreams" ); |
265 | return 1; | 267 | return 1; |
266 | } | 268 | } |
267 | 269 | ||
268 | 270 | ||
269 | int WavPlugin::audioChannels( int ) { | 271 | int WavPlugin::audioChannels( int ) { |
270 | debugMsg( "WavPlugin::audioChannels" ); | 272 | // qDebug( "WavPlugin::audioChannels" ); |
271 | return 2; // ### Always scale audio to stereo samples | 273 | return d->chunkdata.channels;// 2; // ### Always scale audio to stereo samples |
272 | } | 274 | } |
273 | 275 | ||
274 | 276 | ||
275 | int WavPlugin::audioFrequency( int ) { | 277 | int WavPlugin::audioFrequency( int ) { |
276 | debugMsg( "WavPlugin::audioFrequency" ); | 278 | // qDebug( "WavPlugin::audioFrequency %d", d->chunkdata.samplesPerSec ); |
277 | return 44100; // ### Always scale to frequency of 44100 | 279 | return d->chunkdata.samplesPerSec; //44100; // ### Always scale to frequency of 44100 |
278 | } | 280 | } |
279 | 281 | ||
280 | 282 | ||
281 | int WavPlugin::audioSamples( int ) { | 283 | int WavPlugin::audioSamples( int ) { |
282 | debugMsg( "WavPlugin::audioSamples" ); | 284 | // qDebug( "WavPlugin::audioSamples" ); |
283 | return d->samples * 2 / d->chunkdata.channels; // ### Scaled samples will be made stereo, | 285 | return d->samples / d->chunkdata.channels/2; // ### Scaled samples will be made stereo, |
284 | // Therefore if source is mono we will double the number of samples | 286 | // Therefore if source is mono we will double the number of samples |
285 | } | 287 | } |
286 | 288 | ||
287 | 289 | ||
288 | bool WavPlugin::audioSetSample( long, int ) { | 290 | bool WavPlugin::audioSetSample( long, int ) { |
289 | debugMsg( "WavPlugin::audioSetSample" ); | 291 | // qDebug( "WavPlugin::audioSetSample" ); |
290 | return FALSE; | 292 | return FALSE; |
291 | } | 293 | } |
292 | 294 | ||
293 | 295 | ||
294 | long WavPlugin::audioGetSample( int ) { | 296 | long WavPlugin::audioGetSample( int ) { |
295 | debugMsg( "WavPlugin::audioGetSample" ); | 297 | // qDebug( "WavPlugin::audioGetSample" ); |
296 | return 0; | 298 | return 0; |
297 | } | 299 | } |
298 | 300 | ||
299 | /* | 301 | /* |
300 | bool WavPlugin::audioReadSamples( short *, int, long, int ) { | 302 | bool WavPlugin::audioReadSamples( short *, int, long, int ) { |
301 | debugMsg( "WavPlugin::audioReadSamples" ); | 303 | debugMsg( "WavPlugin::audioReadSamples" ); |
@@ -319,16 +321,21 @@ bool WavPlugin::audioReadStereoSamples( short *output, long samples, long& sampl | |||
319 | debugMsg( "WavPlugin::audioReadStereoSamples" ); | 321 | debugMsg( "WavPlugin::audioReadStereoSamples" ); |
320 | return !d->add( output, samples, samplesMade, TRUE ); | 322 | return !d->add( output, samples, samplesMade, TRUE ); |
321 | } | 323 | } |
322 | */ | 324 | */ |
323 | 325 | ||
324 | bool WavPlugin::audioReadSamples( short *output, int channels, long samples, long& samplesMade, int ) { | 326 | bool WavPlugin::audioReadSamples( short *output, int channels, long samples, long& samplesMade, int ) { |
325 | debugMsg( "WavPlugin::audioReadSamples" ); | 327 | // qDebug( "WavPlugin::audioReadSamples" ); |
326 | return d->add( output, samples, samplesMade, channels != 1 ); | 328 | return d->add( output, samples, samplesMade, channels != 1 ); |
327 | } | 329 | } |
328 | 330 | ||
329 | double WavPlugin::getTime() { | 331 | double WavPlugin::getTime() { |
330 | debugMsg( "WavPlugin::getTime" ); | 332 | // qDebug( "WavPlugin::getTime" ); |
331 | return 0.0; | 333 | return 0.0; |
332 | } | 334 | } |
333 | 335 | ||
336 | int WavPlugin::audioBitsPerSample( int ) { | ||
337 | // qDebug( "WavPlugin::audioFormat %d", d->chunkdata.wBitsPerSample ); | ||
338 | return d->chunkdata.wBitsPerSample; // | ||
339 | } | ||
340 | |||
334 | 341 | ||