audio_sample.cc

00001 /*
00002  *  Player - One Hell of a Robot Server
00003  *  Copyright (C) 2003
00004  *     Brian Gerkey
00005  *
00006  *
00007  *  This program is free software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation; either version 2 of the License, or
00010  *  (at your option) any later version.
00011  *
00012  *  This program is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *  GNU General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU General Public License
00018  *  along with this program; if not, write to the Free Software
00019  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  */
00022 
00023 #include <libplayercore/playercore.h>
00024 #include "audio_sample.h"
00025 
00026 #include <stdlib.h>
00027 #include <iostream>
00028 
00029 using namespace std;
00030 
00032 //      Class functions
00034 
00035 // Constructor
00036 AudioSample::AudioSample (void)
00037 {
00038         // Set the sample type to none
00039         type = SAMPLE_TYPE_NONE;
00040         // Blank wave data
00041         numChannels = 0;
00042         sampleRate = 0;
00043         byteRate = 0;
00044         blockAlign = 0;
00045         bitsPerSample = 0;
00046         numFrames = 0;
00047         // Blank storage variables
00048         position = 0;
00049         waveFile = NULL;
00050         filePath = NULL;
00051         headerSize = 0;
00052         dataLength = 0;
00053         data = NULL;
00054 }
00055 
00056 // Constructor from Player type
00057 AudioSample::AudioSample (const player_audio_wav_t *source)
00058 {
00059         // Set the sample type to none
00060         type = SAMPLE_TYPE_NONE;
00061         // Blank wave data
00062         numChannels = 0;
00063         sampleRate = 0;
00064         byteRate = 0;
00065         blockAlign = 0;
00066         bitsPerSample = 0;
00067         numFrames = 0;
00068         // Blank storage variables
00069         position = 0;
00070         waveFile = NULL;
00071         filePath = NULL;
00072         headerSize = 0;
00073         dataLength = 0;
00074         data = NULL;
00075 
00076         if (!FromPlayer (source))
00077                 PLAYER_ERROR ("unable to create audio sample from Player data");
00078 }
00079 
00080 // Constructor from raw data
00081 // source: the data to copy from
00082 // length: number of _bytes_ in the data (not frames)
00083 // channels: number of channels in the data
00084 // sr: sample rate
00085 // bps: bits per sample (8, 16, etc)
00086 AudioSample::AudioSample (const uint8_t *source, uint32_t length, uint16_t channels, uint32_t sr, uint16_t bps)
00087 {
00088         // Set the sample type to memory
00089         type = SAMPLE_TYPE_MEM;
00090         // Set wave info
00091         numChannels = channels;
00092         sampleRate = sr;
00093         bitsPerSample = bps;
00094         // Calculate the other format info
00095         blockAlign = numChannels * (bitsPerSample / 8);
00096         byteRate = sampleRate * blockAlign;
00097 
00098         // Blank other storage variables
00099         position = 0;
00100         waveFile = NULL;
00101         filePath = NULL;
00102         headerSize = 0;
00103         dataLength = 0;
00104         data = NULL;
00105 
00106         // Allocate memory for the data
00107         if ((data = new uint8_t[length]) == NULL)
00108         {
00109                 PLAYER_ERROR ("Failed to allocate memory for wave data");
00110                 return;
00111         }
00112         // Copy the wave data across
00113         memcpy (data, source, length);
00114         dataLength = length;
00115         numFrames = dataLength / blockAlign;
00116 }
00117 
00118 // Destructor
00119 AudioSample::~AudioSample (void)
00120 {
00121         if (waveFile != NULL)
00122         {
00123                 if (type != SAMPLE_TYPE_FILE)
00124                         PLAYER_WARN ("file descriptor not NULL for non-file sample");
00125                 fclose (waveFile);
00126         }
00127         if (filePath != NULL)
00128         {
00129                 if (type != SAMPLE_TYPE_FILE)
00130                         PLAYER_WARN ("file path not NULL for non-file sample");
00131                 free (filePath);
00132         }
00133         if (data != NULL)
00134         {
00135                 if (type != SAMPLE_TYPE_MEM)
00136                         PLAYER_WARN ("data not NULL for non-mem sample");
00137                 delete[] data;
00138         }
00139 }
00140 
00142 //      Data management functions
00144 
00145 // Set the position of reading in the data
00146 void AudioSample::SetDataPosition (uint32_t newPosition)
00147 {
00148         // If the new position is beyond the end of the data, set it to the end
00149         if ((newPosition * blockAlign) > dataLength)
00150                 position = dataLength;
00151         else
00152                 // Otherwise just set it to the new position
00153                 position = newPosition * blockAlign;
00154 }
00155 
00156 uint32_t AudioSample::GetDataPosition (void) const
00157 {
00158         return position / blockAlign;
00159 }
00160 
00161 uint32_t AudioSample::GetDataLength (void) const
00162 {
00163         if (type == SAMPLE_TYPE_FILE || type == SAMPLE_TYPE_MEM)
00164                 return dataLength / blockAlign;
00165         else    // SAMPLE_TYPE_NONE or some other value that type really shouldn't be
00166                 return 0;
00167 }
00168 
00169 // Get a block of wave data
00170 // frameCount: The number of _frames_ to get (not bytes!)
00171 // buffer: The buffer to store the frames in (must allocate enough)
00172 // Returns: the number of frames actually stored in buffer
00173 int AudioSample::GetData (int frameCount, uint8_t *buffer)
00174 {
00175         int bytesCopied = 0;
00176 
00177         if (buffer == NULL)
00178         {
00179                 // Can't copy to a NULL buffer
00180                 PLAYER_WARN ("Can't copy data into a null buffer");
00181                 return -1;
00182         }
00183 
00184         // Number of bytes to copy is number of frames to copy * frame size
00185         int bytesCount = frameCount * blockAlign;
00186 
00187         if (type == SAMPLE_TYPE_NONE)
00188         {
00189                 PLAYER_WARN ("Attempt to get data from an empty sample");
00190                 return -1;
00191         }
00192         else if (type == SAMPLE_TYPE_FILE)
00193         {
00194                 // Seek to the position to get data from in the file (offset by header size)
00195                 // (Have to do this in case SetDataPosition was used since the last read)
00196                 if (fseek (waveFile, headerSize + position, SEEK_SET) != 0)
00197                 {
00198                         PLAYER_ERROR1 ("Error seeking to current position in wave file: %s", strerror (errno));
00199                         return -1;
00200                 }
00201                 // Number of bytes to copy shouldn't take us beyond the end of the data
00202                 int bytesToCopy = (position + bytesCount) > dataLength ? (dataLength - position) : bytesCount;
00203                 // Read into the buffer provided the number of bytes to copy
00204                 if ((bytesCopied = fread (buffer, 1, bytesToCopy, waveFile)) == 0)
00205                 {
00206                         if (feof (waveFile))
00207                                 PLAYER_ERROR ("End of file reading wave data");
00208                         else
00209                                 PLAYER_ERROR1 ("Error reading wave data from file: %s", strerror (errno));
00210                         return 0;
00211                 }
00212                 else if (bytesCopied < bytesToCopy)
00213                 {
00214                         PLAYER_ERROR1 ("Error reading wave data from file (didn't get enough bytes): %s\n", strerror (errno));
00215                         // Return what we got, driver will assume end of data and move to next sample in queue
00216                 }
00217         }
00218         else if (type == SAMPLE_TYPE_MEM)
00219         {
00220                 // If there is no data, return 0 (end of sample)
00221                 if (dataLength == 0)
00222                         return 0;
00223                 // Number of bytes to copy shouldn't take us beyond the end of the array
00224                 int bytesToCopy = (position + bytesCount) > dataLength ? (dataLength - position) : bytesCount;
00225                 // Copy from data[position] to data[position + bytesToCopy]
00226                 memcpy (buffer, &data[position], bytesToCopy);
00227                 bytesCopied = bytesToCopy;
00228         }
00229 
00230         // Update position with the new position (old position + length actually read)
00231         position += bytesCopied;
00232         // Return the number of frames actually copied
00233         return bytesCopied / blockAlign;
00234 }
00235 
00236 // Clears the entire sample, making it a SAMPLE_TYPE_NONE
00237 void AudioSample::ClearSample (void)
00238 {
00239         // For FILE type, need to close the file and remove the file name string
00240         if (type == SAMPLE_TYPE_FILE)
00241         {
00242                 if (waveFile != NULL)
00243                         fclose (waveFile);
00244                 if (filePath != NULL)
00245                         free (filePath);
00246         }
00247         // For MEM type, need to delete any stored data
00248         else if (type == SAMPLE_TYPE_MEM)
00249         {
00250                 if (data != NULL)
00251                         delete[] data;
00252         }
00253         // Do nothing for SAMPLE_TYPE_NONE
00254 
00255         // In both cases, set everything to 0
00256         // Set the sample type to none
00257         type = SAMPLE_TYPE_NONE;
00258         // Blank wave data
00259         numChannels = 0;
00260         sampleRate = 0;
00261         byteRate = 0;
00262         blockAlign = 0;
00263         bitsPerSample = 0;
00264         numFrames = 0;
00265         // Blank storage variables
00266         position = 0;
00267         waveFile = NULL;
00268         filePath = NULL;
00269         headerSize = 0;
00270         dataLength = 0;
00271         data = NULL;
00272 }
00273 
00274 // Fills the data with a constant silence value
00275 // time: The length of time to fill
00276 bool AudioSample::FillSilence (uint32_t time)
00277 {
00278         // First, make sure this sample is empty
00279         if (type != SAMPLE_TYPE_NONE)
00280         {
00281                 PLAYER_ERROR ("Tried to set non-empty sample to silence");
00282                 return false;
00283         }
00284 
00285         // Next, create a data buffer
00286         dataLength = static_cast<uint32_t> ((static_cast<double> (time) / 1000.0f) * byteRate);
00287         if ((data = new uint8_t[dataLength]) == NULL)
00288         {
00289                 PLAYER_ERROR ("Failed to allocate memory for wave data");
00290                 return false;
00291         }
00292         // Set the wave data to zero
00293         memset (data, 0, dataLength);
00294         numFrames = dataLength / blockAlign;
00295 
00296         // Set type to MEM
00297         type = SAMPLE_TYPE_MEM;
00298 
00299         return true;
00300 }
00301 
00303 //      Data conversion functions
00305 
00306 // Copies the data from a loaded wave file to the player struct for wave data
00307 // If the wave data doesn't match one of the possible formats supported by the
00308 // player format flags, the copy isn't performed and an error is returned
00309 bool AudioSample::ToPlayer (player_audio_wav_t *dest)
00310 {
00311 
00312 
00313         if (type == SAMPLE_TYPE_NONE || (type == SAMPLE_TYPE_MEM && data == NULL) || (type == SAMPLE_TYPE_FILE && filePath == NULL))
00314         {
00315                 PLAYER_WARN ("No sample to convert to player format");
00316                 return false;
00317         }
00318 
00319         // Set the format flags
00320         dest->format = PLAYER_AUDIO_FORMAT_RAW;
00321         if (numChannels == 2)
00322                 dest->format |= PLAYER_AUDIO_STEREO;
00323         else if (numChannels != 1)
00324         {
00325                 PLAYER_ERROR ("Cannot convert wave to player struct: wrong number of channels");
00326                 return false;
00327         }
00328         switch (sampleRate)
00329         {
00330                 case 11025:
00331                         dest->format |= PLAYER_AUDIO_FREQ_11k;
00332                         break;
00333                 case 22050:
00334                         dest->format |= PLAYER_AUDIO_FREQ_22k;
00335                         break;
00336                 case 44100:
00337                         dest->format |= PLAYER_AUDIO_FREQ_44k;
00338                         break;
00339                 case 48000:
00340                         dest->format |= PLAYER_AUDIO_FREQ_48k;
00341                         break;
00342                 default:
00343                         PLAYER_ERROR ("Cannot convert wave to player struct: wrong sample rate");
00344                         return false;
00345         }
00346 
00347         switch (bitsPerSample)
00348         {
00349                 case 8:
00350                         dest->format |= PLAYER_AUDIO_8BIT;
00351                         break;
00352                 case 16:
00353                         dest->format |= PLAYER_AUDIO_16BIT;
00354                         break;
00355                 case 24:
00356                         dest->format |= PLAYER_AUDIO_24BIT;
00357                         break;
00358                 default:
00359                         PLAYER_ERROR ("Cannot convert wave to player struct: wrong format (bits per sample)");
00360                         return false;
00361         }
00362 
00363         // Copy as many frames as can fit into PLAYER_MAX_MESSAGE_SIZE bytes
00364         uint32_t framesToCopy = PLAYER_MAX_MESSAGE_SIZE / blockAlign;
00365         if (numFrames < framesToCopy)
00366                 framesToCopy = numFrames;
00367         if (type == SAMPLE_TYPE_FILE)
00368         {
00369                 // Remember the current data position
00370                 uint32_t currentPos = GetDataPosition ();
00371                 // Move to the start of the wave
00372                 SetDataPosition (0);
00373                 // Grab some data, put it in the player struct
00374                 printf ("copied %d frames\n", GetData (framesToCopy, dest->data));
00375                 // Move back to where we were
00376                 SetDataPosition (currentPos);
00377         }
00378         else
00379         {
00380                 // Just copy. Nice and easy.
00381                 memcpy (&dest->data, data, framesToCopy * blockAlign);
00382         }
00383         dest->data_count = framesToCopy * blockAlign;
00384 
00385         return true;
00386 }
00387 
00388 bool AudioSample::FromPlayer (const player_audio_wav_t *source)
00389 {
00390         // Set format information
00391         if ((source->format & PLAYER_AUDIO_FORMAT_BITS) != PLAYER_AUDIO_FORMAT_RAW)
00392         {
00393                 // Can't handle non-raw data
00394                 PLAYER_ERROR ("Cannot play non-raw audio data");
00395                 return false;
00396         }
00397 
00398         // Clean out any existing data
00399         ClearSample ();
00400 
00401         if (source->format & PLAYER_AUDIO_STEREO)
00402                 numChannels = 2;
00403         else
00404                 numChannels = 1;
00405 
00406         if ((source->format & PLAYER_AUDIO_FREQ) == PLAYER_AUDIO_FREQ_11k)
00407                 sampleRate = 11025;
00408         else if ((source->format & PLAYER_AUDIO_FREQ) == PLAYER_AUDIO_FREQ_22k)
00409                 sampleRate = 22050;
00410         else if ((source->format & PLAYER_AUDIO_FREQ) == PLAYER_AUDIO_FREQ_44k)
00411                 sampleRate = 44100;
00412         else if ((source->format & PLAYER_AUDIO_FREQ) == PLAYER_AUDIO_FREQ_48k)
00413                 sampleRate = 48000;
00414 
00415         if ((source->format & PLAYER_AUDIO_BITS) == PLAYER_AUDIO_8BIT)
00416         {
00417                 bitsPerSample = 8;
00418         }
00419         else if ((source->format & PLAYER_AUDIO_BITS) == PLAYER_AUDIO_16BIT)
00420         {
00421                 bitsPerSample = 16;
00422         }
00423         else if ((source->format & PLAYER_AUDIO_BITS) == PLAYER_AUDIO_24BIT)
00424         {
00425                 bitsPerSample = 24;
00426         }
00427 
00428         // Calculate the other format info
00429         blockAlign = numChannels * (bitsPerSample / 8);
00430         byteRate = sampleRate * blockAlign;
00431 
00432         // Allocate memory for the data if necessary
00433         if ((data = new uint8_t[source->data_count]) == NULL)
00434         {
00435                 PLAYER_ERROR ("Failed to allocate memory for wave data");
00436                 return false;
00437         }
00438         // Copy the wave data across
00439         memcpy (data, source->data, source->data_count);
00440         dataLength = source->data_count;
00441         numFrames = dataLength / blockAlign;
00442 
00443         // Set type to MEM
00444         type = SAMPLE_TYPE_MEM;
00445 
00446         return true;
00447 }
00448 
00450 //      File management functions
00452 
00453 // Load a wave file from disc
00454 // filePath: The path to the file to load
00455 // Returns: true for success, false otherwise
00456 bool AudioSample::LoadFile (const char *fileName)
00457 {
00458         char tag[5];
00459         uint16_t tempUShort = 0;
00460         uint32_t tempUInt = 0, subChunk1Size = 0;
00461 
00462         // First of all, make sure this sample is empty
00463         ClearSample ();
00464 
00465         // Try to open the wave file
00466         if ((waveFile = fopen (fileName, "r")) == NULL)
00467         {
00468                 PLAYER_ERROR1 ("Couldn't open wave file for reading: %s", strerror (errno));
00469                 return false;
00470         }
00471 
00472         // Wave file should be in the format (header, format chunk, data chunk), where:
00473         // header = 4+4+4 bytes: "RIFF", size, "WAVE"
00474         // format = 4+4+2+2+4+4+2+2[+2] bytes:
00475         //          "fmt ", size, 1, numChannels, sampleRate, byteRate, blockAlign,
00476         //          bitsPerSample, [extraParamsSize] (not present for PCM)
00477         // data = 4+4+? bytes: "data", size, data bytes...
00478 
00479         // Read the header - first the RIFF tag
00480         if (fgets (tag, 5, waveFile) == NULL)
00481         {
00482                 PLAYER_ERROR ("Error reading tag from wave file");
00483                 return false;
00484         }
00485         if (strcmp (tag, "RIFF") != 0)
00486         {
00487                 PLAYER_ERROR ("Bad WAV format: missing RIFF tag");
00488                 return false;
00489         }
00490         // Get the size of the file
00491         if (fread (&tempUInt, 4, 1, waveFile) != 1)
00492         {
00493                 if (feof (waveFile))
00494                         PLAYER_ERROR ("End of file reading WAV header");
00495                 else
00496                         PLAYER_ERROR ("Error reading WAV header");
00497                 return false;
00498         }
00499         // Check the file size isn't stupid - should at least have size of all
00500         // chunks (excluding 2 fields already done)
00501         if (tempUInt < 36)
00502         {
00503                 PLAYER_ERROR ("WAV file too short: missing chunk information");
00504                 return false;
00505         }
00506         // Next tag should say "WAVE"
00507         if (fgets (tag, 5, waveFile) == NULL)
00508         {
00509                 PLAYER_ERROR ("Error reading tag from wave file");
00510                 return false;
00511         }
00512         if (strcmp (tag, "WAVE") != 0)
00513         {
00514                 PLAYER_ERROR ("Bad WAV format: missing WAVE tag");
00515                 return false;
00516         }
00517 
00518         // Next is the format information chunk, starting with a "fmt " tag
00519         if (fgets (tag, 5, waveFile) == NULL)
00520         {
00521                 PLAYER_ERROR ("Error reading tag from wave file");
00522                 return false;
00523         }
00524         if (strcmp (tag, "fmt ") != 0)
00525         {
00526                 PLAYER_ERROR ("Bad WAV format: missing fmt  tag");
00527                 return false;
00528         }
00529         // Followed by size of this chunk - should be 16, may be 18 if not quite
00530         // following the format correctly
00531         if (fread (&subChunk1Size, 4, 1, waveFile) != 1)
00532         {
00533                 if (feof (waveFile))
00534                         PLAYER_ERROR ("End of file reading WAV format");
00535                 else
00536                         PLAYER_ERROR ("Error reading WAV format");
00537                 return false;
00538         }
00539         if (subChunk1Size != 16 && subChunk1Size != 18)
00540         {
00541                 PLAYER_ERROR ("WAV file too short: missing chunk information");
00542                 return false;
00543         }
00544         // Audio format is next - if not 1, can't read this file cause it isn't PCM
00545         if (fread (&tempUShort, 2, 1, waveFile) != 1)
00546         {
00547                 if (feof (waveFile))
00548                         PLAYER_ERROR ("End of file reading WAV format");
00549                 else
00550                         PLAYER_ERROR ("Error reading WAV format");
00551                 return false;
00552         }
00553         if (tempUShort != 1)
00554         {
00555                 PLAYER_ERROR ("WAV file not in PCM format");
00556                 return false;
00557         }
00558         // Having got this far, we can now start reading data we want to keep
00559         // Read the number of channels
00560         if (fread (&numChannels, 2, 1, waveFile) != 1)
00561         {
00562                 if (feof (waveFile))
00563                         PLAYER_ERROR ("End of file reading WAV num channels");
00564                 else
00565                         PLAYER_ERROR ("Error reading WAV num channels");
00566                 ClearSample ();
00567                 return false;
00568         }
00569         // Read the sample rate
00570         if (fread (&sampleRate, 4, 1, waveFile) != 1)
00571         {
00572                 if (feof (waveFile))
00573                         PLAYER_ERROR ("End of file reading WAV sample rate");
00574                 else
00575                         PLAYER_ERROR ("Error reading WAV sample rate");
00576                 ClearSample ();
00577                 return false;
00578         }
00579         // Read the byte rate
00580         if (fread (&byteRate, 4, 1, waveFile) != 1)
00581         {
00582                 if (feof (waveFile))
00583                         PLAYER_ERROR ("End of file reading WAV byte rate");
00584                 else
00585                         PLAYER_ERROR ("Error reading WAV byte rate");
00586                 ClearSample ();
00587                 return false;
00588         }
00589         // Read the block align
00590         if (fread (&blockAlign, 2, 1, waveFile) != 1)
00591         {
00592                 if (feof (waveFile))
00593                         PLAYER_ERROR ("End of file reading WAV block align");
00594                 else
00595                         PLAYER_ERROR ("Error reading WAV block align");
00596                 ClearSample ();
00597                 return false;
00598         }
00599         // Read the bits per sample
00600         if (fread (&bitsPerSample, 2, 1, waveFile) != 1)
00601         {
00602                 if (feof (waveFile))
00603                         PLAYER_ERROR ("End of file reading WAV bits per sample");
00604                 else
00605                         PLAYER_ERROR ("Error reading WAV bits per sample");
00606                 ClearSample ();
00607                 return false;
00608         }
00609         // If the size of this chunk was 18, get those extra two bytes
00610         if (subChunk1Size == 18)
00611         {
00612                 if (fread (&tempUShort, 2, 1, waveFile) != 1)
00613                 {
00614                         if (feof (waveFile))
00615                                 PLAYER_ERROR ("End of file reading blank 2 bytes");
00616                         else
00617                                 PLAYER_ERROR ("Error reading WAV blank 2 bytes");
00618                         ClearSample ();
00619                         return false;
00620                 }
00621         }
00622 
00623         // On to the data chunk, again starting with a tag
00624         if (fgets (tag, 5, waveFile) == NULL)
00625         {
00626                 PLAYER_ERROR ("Error reading tag from wave file");
00627                 ClearSample ();
00628                 return false;
00629         }
00630         if (strcmp (tag, "data") != 0)
00631         {
00632                 PLAYER_ERROR ("Bad WAV format: missing data tag");
00633                 ClearSample ();
00634                 return false;
00635         }
00636         // Size of the wave data
00637         if (fread (&dataLength, 4, 1, waveFile) != 1)
00638         {
00639                 if (feof (waveFile))
00640                         PLAYER_ERROR ("End of file reading WAV data size");
00641                 else
00642                         PLAYER_ERROR ("Error reading WAV data size");
00643                 ClearSample ();
00644                 return false;
00645         }
00646 
00647         // The file pointer is now positioned at the start of the data.
00648         // Store the header size (for moving around the wave file easily later on).
00649         headerSize = ftell (waveFile);
00650         // Also store the file path
00651         filePath = strdup (fileName);
00652         // Go to the end of the file and get position in order to get the length
00653         // of the file, subtract headerSize to get the position
00654         fseek (waveFile, 0, SEEK_END);
00655         dataLength = ftell (waveFile) - headerSize;
00656         // Back to the start of the data again
00657         fseek (waveFile, headerSize, SEEK_SET);
00658         // Calculate the number of frames in the data
00659         numFrames = dataLength / (numChannels * (bitsPerSample / 8));
00660         // Set type
00661         type = SAMPLE_TYPE_FILE;
00662 
00663         return true;
00664 }
00665 
00666 void AudioSample::CloseFile (void)
00667 {
00668         // Just clear the sample, that'll close the file and clean up anything else
00669         ClearSample ();
00670 }
00671 
00673 //      Wave format functions
00675 
00676 // Checks if the format information of this sample is the same as rhs
00677 // rhs: A pointer to an AudioSample
00678 // Returns: true if same, false if different or rhs is NULL
00679 bool AudioSample::SameFormat (const AudioSample *rhs)
00680 {
00681         if (!rhs || type == SAMPLE_TYPE_NONE)
00682                 return false;
00683         if (numChannels == rhs->GetNumChannels () &&
00684                    sampleRate == rhs->GetSampleRate () &&
00685                    bitsPerSample == rhs->GetBitsPerSample ())
00686                 return true;
00687         return false;
00688 }
00689 
00690 // Copies the format of rhs
00691 // rhs: A pointer to an AudioSample whose format should be copied
00692 void AudioSample::CopyFormat (const AudioSample *rhs)
00693 {
00694         if (!rhs || type == SAMPLE_TYPE_NONE)
00695                 return;
00696         numChannels = rhs->GetNumChannels ();
00697         sampleRate = rhs->GetSampleRate ();
00698         byteRate = rhs->GetByteRate ();
00699         blockAlign = rhs->GetBlockAlign ();
00700         bitsPerSample = rhs->GetBitsPerSample ();
00701 }
00702 
00704 //      Other useful functions
00706 
00707 void AudioSample::PrintWaveInfo (void)
00708 {
00709         if (type == SAMPLE_TYPE_FILE)
00710                 cout << "File sample, path: " << filePath << endl;
00711         else if (type == SAMPLE_TYPE_MEM)
00712                 cout << "Memory sample" << endl;
00713         else
00714                 cout << "Empty sample" << endl;
00715         cout << "Num channels:\t" << numChannels << endl;
00716         cout << "Sample rate:\t" << sampleRate << endl;
00717         cout << "Byte rate:\t" << byteRate << endl;
00718         cout << "Block align:\t" << blockAlign << endl;
00719         cout << "Format:\t\t" << endl;
00720         switch (bitsPerSample)
00721         {
00722                 case 8:
00723                         cout << "Unsigned 8 bit" << endl;
00724                         break;
00725                 case 16:
00726                         cout << "Signed 16 bit little-endian" << endl;
00727                         break;
00728                 case 24:
00729                         if ((blockAlign / numChannels) == 3)
00730                                 cout << "Signed 24 bit 3-byte little-endian" << endl;
00731                         else
00732                                 cout << "Signed 24 bit little-endian" << endl;
00733                         break;
00734                 case 32:
00735                         cout << "Signed 32 bit little-endian" << endl;
00736                         break;
00737                 default:
00738                         cout << "Unplayable format: " << bitsPerSample << " bit" << endl;
00739         }
00740         cout << "Num frames:\t" << numFrames << endl;
00741         cout << "Data length:\t" << dataLength << endl;
00742         if (type == SAMPLE_TYPE_FILE)
00743                 cout << "Frames start at:\t" << headerSize << endl;
00744 }

Last updated 12 September 2005 21:38:45