sample.cpp

Go to the documentation of this file.
00001 /* $Id: sample.cpp 191 2005-08-05 00:55:59Z tapted $ $URL: svn+ssh://pc-g33-9.it.usyd.edu.au/var/svn/pub/taptaudio/trunk/src/sample.cpp $ */
00002 #include "sample.h"
00003 
00004 /**\file sample.cpp
00005  * Implementation of the ASSample classes
00006  * \author Trent Apted <tapted@it.usyd.edu.au>
00007  * $Revision: 191 $
00008  * $Date: 2005-08-05 10:55:59 +1000 (Fri, 05 Aug 2005) $
00009  */
00010 
00011 #ifdef HAVE_CONFIG_H
00012 #include "config.h"
00013 #endif
00014 
00015 #include <string.h>
00016 
00017 #include "sndfile.h"
00018 
00019 template <>
00020     sf_count_t lsf_read(SNDFILE *sndfile, short* data, sf_count_t items) {
00021         return sf_read_short(sndfile, data, items);
00022     }
00023 template <>
00024     sf_count_t lsf_read(SNDFILE *sndfile, int* data, sf_count_t items) {
00025         return sf_read_int(sndfile, data, items);
00026     }
00027 template <>
00028     sf_count_t lsf_read(SNDFILE *sndfile, float* data, sf_count_t items) {
00029         return sf_read_float(sndfile, data, items);
00030     }
00031 template <>
00032     sf_count_t lsf_read(SNDFILE *sndfile, double* data, sf_count_t items) {
00033         return sf_read_double(sndfile, data, items);
00034     }
00035 
00036 Recording::Recording(unsigned long initial_size,
00037                      unsigned chans,
00038                      AUDIO_FORMAT format,
00039                      double samplerate)
00040     :
00041     reserved(initial_size)
00042 {
00043     data = new Uint8[reserved];
00044     channels = chans;
00045     bytes_size = 0;
00046     rate = samplerate;
00047     fmt = format;
00048 }
00049 Recording::~Recording() {
00050     delete[] static_cast<Uint8*>(data);
00051     data = 0;
00052 }
00053 
00054 void Recording::fill(const void *more, unsigned long sz) {
00055     if (bytes_size + sz > reserved) {
00056         memcpy(static_cast<Uint8*>(data) + bytes_size, more, reserved-bytes_size);
00057         bytes_size = reserved;
00058     } else {
00059         memcpy(static_cast<Uint8*>(data) + bytes_size, more, sz);
00060         bytes_size += sz;
00061     }
00062 }
00063 
00064 void Recording::skipfill(const void *more, unsigned long sz, unsigned block) {
00065     sz /= 2;
00066     unsigned long szavail = bytes_size + sz > reserved ? reserved - bytes_size : sz;
00067     unsigned long nblocks = szavail / block;
00068     DODEBUG(INTERRUPT, ("[At] At skipfill(more = %p, sz = %lu, block = %u), szavail = %lu, nblocks = %lu",
00069                         more, sz, block, szavail, nblocks));
00070     Uint8 *to = static_cast<Uint8*>(data) + bytes_size;
00071     const Uint8 *from = static_cast<const Uint8*>(more);
00072     for (unsigned b = 0; b < nblocks; ++b) {
00073         memcpy(to, from, block);
00074         to += block;
00075         from += 2*block;
00076     }
00077     bytes_size += szavail;
00078 }
00079 
00080 void Recording::trim() {
00081     if (reserved > bytes_size) {
00082         void* new_buf = new Uint8[bytes_size];
00083         memcpy(new_buf, data, bytes_size);
00084         delete[] static_cast<Uint8*>(data);
00085         data = new_buf;
00086     }
00087 }
00088 
00089 void Recording::fillSilence(unsigned long sz) {
00090     if (bytes_size + sz > reserved) {
00091         memset(static_cast<Uint8*>(data) + bytes_size, 0, reserved-bytes_size);
00092         bytes_size = reserved;
00093     } else {
00094         memset(static_cast<Uint8*>(data) + bytes_size, 0, sz);
00095         bytes_size += sz;
00096     }
00097 }
00098 
00099 void Recording::append(void *more, unsigned long sz) {
00100     if (bytes_size + sz > reserved) {
00101         do {
00102             reserved <<= 1;
00103         } while (bytes_size + sz > reserved);
00104         void* new_buf = new Uint8[reserved];
00105         memcpy(new_buf, data, bytes_size);
00106         delete[] static_cast<Uint8*>(data);
00107         data = new_buf;
00108     }
00109     memcpy(static_cast<Uint8*>(data) + bytes_size, more, sz);
00110     bytes_size += sz;
00111 }
00112 
00113 void PCMSample::mono2stereo(void *newdata,
00114                             const void *olddata,
00115                             unsigned long olddata_bytes,
00116                             unsigned oldframesize) {
00117     for (unsigned long i = 0; i < olddata_bytes; i += oldframesize) {
00118         memcpy(static_cast<Uint8*>(newdata) + 2*i,
00119                static_cast<const Uint8*>(olddata) + i, oldframesize);
00120         memcpy(static_cast<Uint8*>(newdata) + 2*i + oldframesize,
00121                static_cast<const Uint8*>(olddata) + i, oldframesize);
00122     }
00123 //        for (unsigned b = 0; b < oldframesize; ++b)
00124 //            newdata[2*i + b + oldframesize] = newdata[2*i + b] = olddata[i + b];
00125 }
00126 
00127     /* hmmmm this is very dodgy... we don't use this at the moment */
00128 void PCMSample::stereo2mono(Uint8 *newdata,
00129                             const Uint8 *olddata,
00130                             unsigned long olddata_bytes,
00131                             unsigned framesize) {
00132     for (unsigned long i = 0; i < olddata_bytes/2; i += framesize) {
00133         unsigned long accum[2] = {0, 0}; //unsigned long long??
00134         for (unsigned b = 0; b < framesize; ++b) {
00135             accum[0] = (accum[0] << 8) + olddata[2*i + b];
00136             accum[1] = (accum[1] << 8) + olddata[2*i + b + framesize];
00137         }
00138         accum[0] =  static_cast<unsigned long>((0.5 + accum[0] + accum[1]) / 2.0);
00139         for (unsigned b = 0; b < framesize; ++b) {
00140             newdata[i + framesize - b] = accum[0] & 0xff;
00141             accum[0] = accum[0] >> 8 & 0x00ffffff;
00142         }
00143     }
00144 }
00145 
00146 void FileSample::load_sndfile(SNDFILE* sf, SF_INFO &sfinfo, bool forcestereo) {
00147     unsigned  sz = 0;
00148     switch (sfinfo.format & SF_FORMAT_SUBMASK) {
00149         //case SF_FORMAT_DOUBLE: sz = 4;
00150     case SF_FORMAT_FLOAT:
00151     case SF_FORMAT_PCM_32: sz++;
00152     /*case SF_FORMAT_PCM_24:*/ sz++;
00153     case SF_FORMAT_PCM_16: sz++;
00154     case SF_FORMAT_PCM_S8:
00155         /*case SF_FORMAT_PCM_U8:*/ sz++;
00156     }
00157     if (sz == 0) {
00158         throw "Unsupported";
00159     }
00160 
00161     unsigned frame_sz = sz * sfinfo.channels;
00162     channels = sfinfo.channels;
00163     bytes_size = frame_sz * sfinfo.frames;
00164     rate = sfinfo.samplerate;
00165     data = new Uint8[bytes_size];
00166 
00167     sf_count_t numread = 0;
00168 
00169     switch (sfinfo.format & SF_FORMAT_SUBMASK) {
00170     case SF_FORMAT_FLOAT:
00171         numread = sf_readf_float(sf, static_cast<float*>(data), sfinfo.frames);
00172         fmt = AF_Float32;
00173         break;
00174     case SF_FORMAT_PCM_32:
00175         numread = sf_readf_int(sf, static_cast<int*>(data), sfinfo.frames);
00176         fmt = AF_Int32;
00177         break;
00178     case SF_FORMAT_PCM_16:
00179         numread = sf_readf_short(sf, static_cast<short*>(data), sfinfo.frames);
00180         fmt = AF_Int16;
00181         break;
00182     case SF_FORMAT_PCM_S8:
00183         numread = sf_read_raw(sf, data, bytes_size);
00184         fmt = AF_Int8;
00185     }
00186 
00187     if (channels == 1 && forcestereo) {
00188         Uint8 *newdata = new Uint8[bytes_size * 2];
00189         mono2stereo(newdata, data, bytes_size, sz);
00190         delete[] static_cast<Uint8*>(data);
00191         data = newdata;
00192         bytes_size *= 2;
00193         channels = 2;
00194     }
00195 }
00196 
00197 FileSample::FileSample(const std::string &path, bool forcestereo) {
00198     SF_INFO sfinfo;
00199     SNDFILE* sf = sf_open(path.c_str(), SFM_READ, &sfinfo);
00200     if (sf) {
00201         try {
00202             load_sndfile(sf, sfinfo, forcestereo);
00203         } catch (...) {
00204             DODEBUG(ERROR, ("[Ae] Unsupported file format in %s\n",
00205                             path.c_str()));
00206             sf_close(sf);
00207             throw;
00208         }
00209         sf_close(sf);
00210     } else {
00211         DODEBUG(ERROR, ("[Ae] Unable to open %s: %s\n",
00212                         path.c_str(), sf_strerror(sf)));
00213         throw "Unable to open file";
00214     }
00215 }
00216 
00217 FileSample::~FileSample() {
00218     delete[] static_cast<Uint8*>(data);
00219     data = 0;
00220 }
00221 
00222 bool Recording::save(const std::string &path) {
00223     SNDFILE *sf = 0;
00224     SF_INFO sfinfo = {0, static_cast<int>(rate), channels, SF_FORMAT_WAV | SF_ENDIAN_FILE, 1, 0};
00225     sf_count_t numwritten = 0;
00226     switch (fmt) {
00227     case AF_Float32:
00228         sfinfo.frames = bytes_size / (4 * channels);
00229         sfinfo.format |= SF_FORMAT_FLOAT;
00230         if ((sf = sf_open(path.c_str(), SFM_WRITE, &sfinfo)))
00231             numwritten = sf_writef_float(sf, static_cast<float*>(data), bytes_size / (4*channels));
00232         break;
00233     case AF_Int32:
00234         sfinfo.frames = bytes_size / (4 * channels);
00235         sfinfo.format |= SF_FORMAT_PCM_32;
00236         if ((sf = sf_open(path.c_str(), SFM_WRITE, &sfinfo)))
00237             numwritten = sf_writef_int(sf, static_cast<int*>(data), bytes_size / (4*channels));
00238         break;
00239     case AF_Int16:
00240         sfinfo.frames = bytes_size / (2 * channels);
00241         sfinfo.format |= SF_FORMAT_PCM_16;
00242         if ((sf = sf_open(path.c_str(), SFM_WRITE, &sfinfo)))
00243             numwritten = sf_writef_short(sf, static_cast<short*>(data), bytes_size / (2 * channels));
00244         break;
00245     case AF_Int8:
00246         sfinfo.frames = bytes_size / 1;
00247         sfinfo.format |= SF_FORMAT_PCM_S8;
00248         if ((sf = sf_open(path.c_str(), SFM_WRITE, &sfinfo)))
00249             numwritten = sf_write_raw(sf, data, bytes_size);
00250         break;
00251     default:
00252         break;
00253     }
00254     if (numwritten == 0)
00255         sf_perror(sf);
00256 
00257     if (sf)
00258         sf_close(sf);
00259 
00260     return numwritten > 0;
00261 }

Generated on Fri Aug 5 19:43:10 2005 for TaptAudio by  doxygen 1.4.3