00001
00002 #include "sample.h"
00003
00004
00005
00006
00007
00008
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
00124
00125 }
00126
00127
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};
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
00150 case SF_FORMAT_FLOAT:
00151 case SF_FORMAT_PCM_32: sz++;
00152 sz++;
00153 case SF_FORMAT_PCM_16: sz++;
00154 case SF_FORMAT_PCM_S8:
00155 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 }