Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

wavplugin.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/
00020 // L.J.Potter added changes Fri 02-15-2002
00021 
00022 
00023 #include "wavplugin.h"
00024 
00025 /* OPIE */
00026 #include <opie2/odebug.h>
00027 
00028 /* QT */
00029 #include <qfile.h>
00030 
00031 /* STD */
00032 #include <stdio.h>
00033 #include <stdarg.h>
00034 #include <stdlib.h>
00035 #include <errno.h>
00036 #include <unistd.h>
00037 
00038 //#define debugMsg(a)     qDebug(a)
00039 #define debugMsg(a)
00040 
00041 
00042 struct RiffChunk {
00043     char id[4];
00044     Q_UINT32 size;
00045     char data[4];
00046 };
00047 
00048 
00049 struct ChunkData {
00050     Q_INT16 formatTag;
00051     Q_INT16 channels;
00052     Q_INT32 samplesPerSec;
00053     Q_INT32 avgBytesPerSec;
00054     Q_INT16 blockAlign;
00055     Q_INT16 wBitsPerSample;
00056 };
00057 
00058 
00059 const int sound_buffer_size = 512; // 4096; // you got to be kidding right?
00060 
00061 
00062 class WavPluginData {
00063 public:
00064     QFile *input;
00065 
00066     int wavedata_remaining;
00067     ChunkData chunkdata;
00068     RiffChunk chunk;
00069     uchar data[sound_buffer_size+32]; // +32 to handle badly aligned input data
00070     int out,max;
00071     int samples_due;
00072     int samples;
00073 
00074     WavPluginData() {
00075   max = out = sound_buffer_size;
00076   wavedata_remaining = 0;
00077   samples_due = 0;
00078   samples = -1;
00079     }
00080 
00081     // expands out samples to the frequency of 44kHz //not any more
00082     bool add( short *output, long count, long& done, bool stereo )
00083     {
00084   done = 0;
00085 
00086   if ( input == 0 ) {
00087       odebug << "no input" << oendl;
00088       return FALSE;
00089   }
00090 
00091         while ( count ) {
00092             int l,r;
00093             if ( getSample(l, r) == FALSE ) {
00094                 odebug << "didn't get sample" << oendl;
00095                 return FALSE;
00096             }
00097               samples_due += chunkdata.samplesPerSec;
00098               printf("samples due %d\r", samples_due);
00099               fflush(stdout);
00100              while ( count && (samples_due > chunkdata.samplesPerSec) ) {
00101                 *output++ = l;
00102                 if ( stereo )
00103                     *output++ = r;
00104                 samples_due -= chunkdata.samplesPerSec;
00105                 count--;
00106                 done++;
00107             }
00108         }
00109         return TRUE;
00110     }
00111 
00112     bool initialise() {
00113   if ( input == 0 )
00114       return FALSE;
00115 
00116   wavedata_remaining = -1;
00117 
00118   while ( wavedata_remaining == -1 ) {
00119       // Keep reading chunks...
00120       const int n = sizeof(chunk) - sizeof(chunk.data);
00121       int t = input->readBlock( (char*)&chunk, n );
00122       if ( t != n ) {
00123     if ( t == -1 )
00124         return FALSE;
00125     return TRUE;
00126       }
00127       if ( qstrncmp(chunk.id,"data",4) == 0 ) {
00128     samples = wavedata_remaining = chunk.size;
00129       } else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) {
00130     char d[4];
00131     if ( input->readBlock(d,4) != 4 ) {
00132         return FALSE;
00133     }
00134     if ( qstrncmp(d,"WAVE",4) != 0 ) {
00135         // skip
00136         if ( chunk.size > 1000000000 || !input->at(input->at()+chunk.size-4) ) {
00137       return FALSE;
00138         }
00139     }
00140       } else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) {
00141     if ( input->readBlock((char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) ) {
00142         return FALSE;
00143     }
00144 #define WAVE_FORMAT_PCM 1
00145     if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) {
00146         odebug << "WAV file: UNSUPPORTED FORMAT " << chunkdata.formatTag << "" << oendl;
00147         return FALSE;
00148     }
00149       } else {
00150     // ignored chunk
00151     if ( chunk.size > 1000000000 || !input->at(input->at()+chunk.size) ) {
00152         return FALSE;
00153     }
00154       }
00155   } // while
00156   odebug << "bits " << chunkdata.wBitsPerSample << "" << oendl;
00157   return TRUE;
00158     }
00159 
00160 
00161     // gets a sample from the file
00162     bool getSample(int& l, int& r)
00163     {
00164   l = r = 0;
00165 
00166   if ( input == 0 )
00167       return FALSE;
00168 
00169   if ( (wavedata_remaining < 0) || !max )
00170       return FALSE;
00171 
00172   if ( out >= max ) {
00173       max = input->readBlock( (char*)data, (uint)QMIN(sound_buffer_size,wavedata_remaining) );
00174 
00175       wavedata_remaining -= max;
00176 
00177       out = 0;
00178       if ( max <= 0 ) {
00179     max = 0;
00180     return TRUE;
00181       }
00182   }
00183   if ( chunkdata.wBitsPerSample == 8 ) {
00184       l = (data[out++] - 128) * 128;
00185   } else {
00186       l = ((short*)data)[out/2];
00187       out += 2;
00188   }
00189   if ( chunkdata.channels == 1 ) {
00190       r = l;
00191   } else {
00192       if ( chunkdata.wBitsPerSample == 8 ) {
00193     r = (data[out++] - 128) * 128;
00194       } else {
00195     r = ((short*)data)[out/2];
00196     out += 2;
00197       }
00198   }
00199   return TRUE;
00200     } // getSample
00201 
00202 };
00203 
00204 
00205 WavPlugin::WavPlugin() {
00206     d = new WavPluginData;
00207     d->input = 0;
00208 }
00209 
00210 
00211 WavPlugin::~WavPlugin() {
00212     close();
00213     delete d;
00214 }
00215 
00216 
00217 bool WavPlugin::isFileSupported( const QString& path ) {
00218 //    odebug << "WavPlugin::isFileSupported" << oendl;
00219 
00220     char *ext = strrchr( path.latin1(), '.' );
00221 
00222     // Test file extension
00223     if ( ext ) {
00224   if ( strncasecmp(ext, ".raw", 4) == 0 )
00225       return TRUE;
00226   if ( strncasecmp(ext, ".wav", 4) == 0 )
00227       return TRUE;
00228   if ( strncasecmp(ext, ".wave", 4) == 0 )
00229       return TRUE;
00230     }
00231 
00232     return FALSE;
00233 }
00234 
00235 
00236 bool WavPlugin::open( const QString& path ) {
00237 //    odebug << "WavPlugin::open" << oendl;
00238 
00239     d->max = d->out = sound_buffer_size;
00240     d->wavedata_remaining = 0;
00241     d->samples_due = 0;
00242 
00243     d->input = new QFile( path );
00244     if ( d->input->open(IO_ReadOnly) == FALSE ) {
00245   odebug << "couldn't open file" << oendl;
00246   delete d->input;
00247   d->input = 0;
00248   return FALSE;
00249     }
00250 
00251     d->initialise();
00252     qApp->processEvents();
00253 
00254     return TRUE;
00255 }
00256 
00257 
00258 bool WavPlugin::close() {
00259 //    odebug << "WavPlugin::close" << oendl;
00260 
00261     d->input->close();
00262     delete d->input;
00263     d->input = 0;
00264     return TRUE;
00265 }
00266 
00267 
00268 bool WavPlugin::isOpen() {
00269 //    odebug << "WavPlugin::isOpen" << oendl;
00270     return ( d->input != 0 );
00271 }
00272 
00273 
00274 int WavPlugin::audioStreams() {
00275 //    odebug << "WavPlugin::audioStreams" << oendl;
00276     return 1;
00277 }
00278 
00279 
00280 int WavPlugin::audioChannels( int ) {
00281 //    odebug << "WavPlugin::audioChannels" << oendl;
00282     return d->chunkdata.channels;// 2; // ### Always scale audio to stereo samples
00283 }
00284 
00285 
00286 int WavPlugin::audioFrequency( int ) {
00287 //    odebug << "WavPlugin::audioFrequency " << d->chunkdata.samplesPerSec << "" << oendl;
00288     return  d->chunkdata.samplesPerSec; //44100; // ### Always scale to frequency of 44100
00289 }
00290 
00291 
00292 int WavPlugin::audioSamples( int ) {
00293 //    odebug << "WavPlugin::audioSamples" << oendl;
00294     return d->samples / d->chunkdata.channels/2; // ### Scaled samples will be made stereo,
00295         // Therefore if source is mono we will double the number of samples
00296 }
00297 
00298 
00299 bool WavPlugin::audioSetSample( long, int ) {
00300 //    odebug << "WavPlugin::audioSetSample" << oendl;
00301     return FALSE;
00302 }
00303 
00304 
00305 long WavPlugin::audioGetSample( int ) {
00306 //    odebug << "WavPlugin::audioGetSample" << oendl;
00307     return 0;
00308 }
00309 
00310 /*
00311 bool WavPlugin::audioReadSamples( short *, int, long, int ) {
00312     debugMsg( "WavPlugin::audioReadSamples" );
00313     return FALSE;
00314 }
00315 
00316 
00317 bool WavPlugin::audioReReadSamples( short *, int, long, int ) {
00318     debugMsg( "WavPlugin::audioReReadSamples" );
00319     return FALSE;
00320 }
00321 
00322 
00323 bool WavPlugin::audioReadMonoSamples( short *output, long samples, long& samplesMade, int ) {
00324     debugMsg( "WavPlugin::audioReadMonoSamples" );
00325     return !d->add( output, samples, samplesMade, FALSE );
00326 }
00327 
00328 
00329 bool WavPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) {
00330     debugMsg( "WavPlugin::audioReadStereoSamples" );
00331     return !d->add( output, samples, samplesMade, TRUE );
00332 }
00333 */
00334 
00335 bool WavPlugin::audioReadSamples( short *output, int channels, long samples, long& samplesMade, int ) {
00336 //    odebug << "WavPlugin::audioReadSamples" << oendl;
00337     return d->add( output, samples, samplesMade, channels != 1 );
00338 }
00339 
00340 double WavPlugin::getTime() {
00341 //    odebug << "WavPlugin::getTime" << oendl;  //this is a stupid hack here!!
00342   return d->chunkdata.wBitsPerSample; /*0.0*/;
00343 }
00344 
00345 // int WavPlugin::audioBitsPerSample( int ) {
00346 // //    odebug << "WavPlugin::audioFormat " << d->chunkdata.wBitsPerSample << "" << oendl;
00347 //     return d->chunkdata.wBitsPerSample; //
00348 // }
00349 
00350 

Generated on Sat Nov 5 16:15:45 2005 for OPIE by  doxygen 1.4.2