2 * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
4 * This program is licensed under the terms and conditions of the
5 * Apache License, version 2.0. The full text of the Apache License is at
6 * http://www.apache.org/licenses/LICENSE-2.0
10 * @brief Sound Sample APP
11 * Test use with which sound is sounded
19 #include "soundsample_yswavfile.h"
21 //#include "app_log.h"
22 #include "ico_apf_log.h"
24 YsWavFile::YsWavFile()
30 YsWavFile::~YsWavFile()
37 void YsWavFile::Initialize(void)
51 unsigned int YsWavFile::NTimeStep(void) const
53 return SizeInByte() / BytePerTimeStep();
56 YSBOOL YsWavFile::Stereo(void) const
61 unsigned int YsWavFile::BytePerTimeStep(void) const
63 unsigned int nChannel = (YSTRUE == stereo ? 2 : 1);
64 return nChannel * BytePerSample();
67 unsigned int YsWavFile::BitPerSample(void) const
72 unsigned int YsWavFile::BytePerSample(void) const
77 unsigned int YsWavFile::PlayBackRate(void) const
82 unsigned int YsWavFile::SizeInByte(void) const
87 YSBOOL YsWavFile::IsSigned(void) const
92 const unsigned char *YsWavFile::DataPointer(void) const
97 const unsigned char *YsWavFile::DataPointerAtTimeStep(unsigned int ts) const
99 return dat + ts * BytePerTimeStep();
102 static unsigned GetUnsigned(const unsigned char buf[])
104 return buf[0] + buf[1] * 0x100 + buf[2] * 0x10000 + buf[3] * 0x1000000;
107 static unsigned GetUnsignedShort(const unsigned char buf[])
109 return buf[0] + buf[1] * 0x100;
114 YSRESULT YsWavFile::LoadWav(const char fn[])
118 uim_debug("Loading %s", fn);
120 fp = fopen(fn, "rb");
122 unsigned char buf[256];
124 unsigned int fSize, hdrSize, dataSize;
127 unsigned short wFormatTag, nChannels;
128 unsigned nSamplesPerSec, nAvgBytesPerSec;
129 unsigned short nBlockAlign, wBitsPerSample, cbSize;
132 if (fread(buf, 1, 4, fp) != 4) {
133 uim_debug("Error in reading RIFF.");
136 if (strncmp((char *) buf, "RIFF", 4) != 0) {
137 uim_debug("Warning: RIFF not found.");
141 if (fread(buf, 1, 4, fp) != 4) {
142 uim_debug("Error in reading file size.");
145 fSize = GetUnsigned(buf);
146 uim_debug("File Size=%d", fSize + 8);
148 if (fread(buf, 1, 8, fp) != 8) {
149 uim_debug("Error in reading WAVEfmt.");
152 if (strncmp((char *) buf, "WAVEfmt", 7) != 0) {
153 uim_debug("Warning: WAVEfmt not found");
157 if (fread(buf, 1, 4, fp) != 4) {
158 uim_debug("Error in reading header size.");
161 hdrSize = GetUnsigned(buf);
162 uim_debug("Header Size=%d", hdrSize);
167 // DWORD nSamplesPerSec;
168 // DWORD nAvgBytesPerSec;
170 // WORD wBitsPerSample;
172 if (fread(buf, 1, hdrSize, fp) != hdrSize) {
173 uim_debug("Error in reading header.");
176 wFormatTag = GetUnsignedShort(buf);
177 nChannels = GetUnsignedShort(buf + 2);
178 nSamplesPerSec = GetUnsigned(buf + 4);
179 nAvgBytesPerSec = GetUnsigned(buf + 8);
180 nBlockAlign = GetUnsignedShort(buf + 12);
181 wBitsPerSample = (hdrSize >= 16 ? GetUnsignedShort(buf + 14) : 0);
182 cbSize = (hdrSize >= 18 ? GetUnsignedShort(buf + 16) : 0);
184 uim_debug("wFormatTag=%d", wFormatTag);
185 uim_debug("nChannels=%d", nChannels);
186 uim_debug("nSamplesPerSec=%d", nSamplesPerSec);
187 uim_debug("nAvgBytesPerSec=%d", nAvgBytesPerSec);
188 uim_debug("nBlockAlign=%d", nBlockAlign);
189 uim_debug("wBitsPerSample=%d", wBitsPerSample);
190 uim_debug("cbSize=%d", cbSize);
195 if (fread(buf, 1, 4, fp) != 4) {
196 uim_debug("Error while waiting for data.");
200 if ((buf[0] == 'd' || buf[0] == 'D')
201 && (buf[1] == 'a' || buf[1] == 'A') && (buf[2] == 't'
203 && (buf[3] == 'a' || buf[3] == 'A')) {
207 uim_debug("Skipping %c%c%c%c", buf[0], buf[1], buf[2],
209 if (fread(buf, 1, 4, fp) != 4) {
210 uim_debug("Error while skipping unknown block.");
216 l = GetUnsigned(buf);
217 if (fread(buf, 1, l, fp) != l) {
218 uim_debug("Error while skipping unknown block.");
225 if (fread(buf, 1, 4, fp) != 4) {
226 uim_debug("Error in reading data size.");
229 dataSize = GetUnsigned(buf);
230 uim_debug("Data Size=%d (0x%x)", dataSize, dataSize);
232 dat = new unsigned char[dataSize];
233 if ((l = fread(dat, 1, dataSize, fp)) != dataSize) {
234 uim_debug("Warning: File ended before reading all data.");
235 uim_debug(" %d (0x%x) bytes have been read", l, l);
238 stereo = (nChannels == 2 ? YSTRUE : YSFALSE);
239 bit = wBitsPerSample;
240 sizeInBytes = dataSize;
241 rate = nSamplesPerSec;
243 if (wBitsPerSample == 8) {
264 YSRESULT YsWavFile::ConvertTo16Bit(void)
270 if (sizeInBytes > 0 && dat != NULL) {
271 unsigned char *newDat = new unsigned char[sizeInBytes * 2];
272 // for (int i=0; i<sizeInBytes; i++)
273 for (unsigned int i = 0; i < sizeInBytes; i++) {
274 newDat[i * 2] = dat[i];
275 newDat[i * 2 + 1] = dat[i];
288 YSRESULT YsWavFile::ConvertTo8Bit(void)
293 else if (bit == 16) {
294 unsigned char *newDat = new unsigned char[sizeInBytes / 2];
295 // for (int i=0; i<sizeInBytes; i+=2)
296 for (unsigned int i = 0; i < sizeInBytes; i += 2) {
297 newDat[i / 2] = dat[i];
310 YSRESULT YsWavFile::ConvertToStereo(void)
312 if (stereo == YSTRUE) {
317 unsigned char *newDat = new unsigned char[sizeInBytes * 2];
318 // for (int i=0; i<sizeInBytes; i++)
319 for (unsigned int i = 0; i < sizeInBytes; i++) {
320 newDat[i * 2] = dat[i];
321 newDat[i * 2 + 1] = dat[i];
331 else if (bit == 16) {
332 unsigned char *newDat = new unsigned char[sizeInBytes * 2];
333 // for (int i=0; i<sizeInBytes; i+=2)
334 for (unsigned int i = 0; i < sizeInBytes; i += 2) {
335 newDat[i * 2] = dat[i];
336 newDat[i * 2 + 1] = dat[i + 1];
337 newDat[i * 2 + 2] = dat[i];
338 newDat[i * 2 + 3] = dat[i + 1];
352 //YSRESULT YsWavFile::Resample(int newRate)
353 YSRESULT YsWavFile::Resample(unsigned int newRate)
355 if (rate != newRate) {
356 const size_t nChannel = (YSTRUE == stereo ? 2 : 1);
357 const size_t bytePerSample = bit / 8;
358 const size_t bytePerTimeStep = nChannel * bytePerSample;
359 const size_t curNTimeStep = sizeInBytes / bytePerTimeStep;
361 const size_t newNTimeStep = curNTimeStep * newRate / rate;
362 const size_t newSize = newNTimeStep * bytePerTimeStep;
364 unsigned char *newDat;
365 newDat = (0 < newSize ? new unsigned char[newSize] : NULL);
367 if (NULL != newDat) {
368 for (size_t ts = 0; ts < newNTimeStep; ts++) {
369 double oldTimeStepD = (double) curNTimeStep * (double) ts /
370 (double) newNTimeStep;
371 size_t oldTimeStep = (size_t) oldTimeStepD;
372 double param = fmod(oldTimeStepD, 1.0);
373 unsigned char *newTimeStepPtr = newDat + ts * bytePerTimeStep;
375 for (size_t ch = 0; ch < nChannel; ++ch) {
376 if (curNTimeStep - 1 <= oldTimeStep) {
378 GetSignedValue(curNTimeStep - 1, ch);
379 SetSignedValue(newTimeStepPtr + bytePerSample * ch,
382 else if ((0 == oldTimeStep) ||
383 (curNTimeStep - 2 <= oldTimeStep)) {
384 const double value[2] = {
385 (double) GetSignedValue(oldTimeStep, ch),
386 (double) GetSignedValue(oldTimeStep + 1, ch)
388 const int newValue = (int)
389 (value[0] * (1.0 - param) + value[1] * param);
390 SetSignedValue(newTimeStepPtr + bytePerSample * ch,
394 const double v[4] = {
396 (double) GetSignedValue(oldTimeStep - 1, ch),
398 (double) GetSignedValue(oldTimeStep, ch),
400 (double) GetSignedValue(oldTimeStep + 1, ch),
402 (double) GetSignedValue(oldTimeStep + 2, ch)
405 // Cubic interpolation. Linear didn't work well.
407 // x=-1 -> -a+b-c+d=v0 (A)
409 // x= 1 -> a+b+c+d=v2 (C)
410 // x= 2 -> 8a+4b+2c+d=v3 (D)
413 // (A)+(C) => 2b+2d=v0+v2 => b=(v0+v2-2d)/2
415 // (D)-2*(B) => 6a+2b-d=v3-2*v2
416 // => a=(v3-2*v2-2b+d)/6
418 const double d = v[1];
419 const double b = (v[0] + v[2] - 2.0 * d) / 2.0;
421 (v[3] - 2.0 * v[2] - 2.0 * b + d) / 6.0;
422 const double c = v[2] - a - b - d;
424 double newValue = a * param * param * param
425 + b * param * param + c * param + d;
426 SetSignedValue(newTimeStepPtr + bytePerSample * ch,
438 sizeInBytes = newSize;
443 YSRESULT YsWavFile::ConvertToMono(void)
445 if (YSTRUE == stereo) {
446 const size_t bytePerSample = bit / 8;
447 const size_t bytePerTimeStep = 2 * bytePerSample;
448 const size_t nTimeStep = sizeInBytes / bytePerTimeStep;
450 const size_t newSize = nTimeStep * bytePerSample;
452 unsigned char *newDat;
453 newDat = (0 < newSize ? new unsigned char[newSize] : NULL);
454 if (NULL != newDat) {
455 for (size_t ts = 0; ts < nTimeStep; ts++) {
457 (GetSignedValue(ts, 0) + GetSignedValue(ts, 1)) / 2;
458 unsigned char *const newTimeStepPtr =
459 newDat + ts * bytePerSample;
460 SetSignedValue(newTimeStepPtr, newValue);
467 sizeInBytes = newSize;
476 YSRESULT YsWavFile::ConvertToSigned(void)
478 if (isSigned == YSTRUE) {
483 // for (int i = 0; i < sizeInBytes; i++)
484 for (unsigned int i = 0; i < sizeInBytes; i++) {
488 else if (bit == 16) {
489 // for (int i = 0; i < sizeInBytes-1; i+=2)
490 for (unsigned int i = 0; i < sizeInBytes - 1; i += 2) {
492 d = dat[i] + dat[i + 1] * 256;
495 dat[i + 1] = (d >> 8) & 255;
503 YSRESULT YsWavFile::ConvertToUnsigned(void)
505 if (isSigned != YSTRUE) {
510 // for (int i = 0; i < sizeInBytes; i++)
511 for (unsigned int i = 0; i < sizeInBytes; i++) {
515 else if (bit == 16) {
516 // for (int i = 0; i < sizeInBytes-1; i+=2)
517 for (unsigned int i = 0; i < sizeInBytes - 1; i += 2) {
518 int d = dat[i] + dat[i + 1] * 256;
524 dat[i + 1] = (d >> 8) & 255;
532 //int main(int ac,char *av[])
535 // test.LoadWav(av[1]);
539 int YsWavFile::GetNumChannel(void) const
541 return (YSTRUE == stereo ? 2 : 1);
544 int YsWavFile::GetNumSample(void) const
546 return sizeInBytes * 8 / bit;
549 int YsWavFile::GetNumSamplePerChannel(void) const
551 return GetNumSample() / GetNumChannel();
554 size_t YsWavFile::GetUnitSize(void) const
556 return BytePerSample() * GetNumChannel();
559 size_t YsWavFile::GetSamplePosition(int atIndex) const
561 return atIndex * GetNumChannel() * (bit / 8);
564 int YsWavFile::GetSignedValue(int atTimeStep, int channel) const
566 const size_t sampleIdx = GetSamplePosition(atTimeStep);
567 const size_t unitSize = GetUnitSize();
569 if ((sampleIdx + unitSize <= sizeInBytes) &&
570 (0 <= channel) && (channel < GetNumChannel())) {
571 int rawSignedValue = 0;
572 size_t offset = sampleIdx + channel * BytePerSample();
573 switch (BitPerSample()) {
575 if (YSTRUE == isSigned) {
576 rawSignedValue = dat[offset];
577 if (128 <= rawSignedValue) {
578 rawSignedValue -= 256;
582 rawSignedValue = dat[offset] - 128;
586 // Assume little endian
587 rawSignedValue = dat[offset] + 256 * dat[offset + 1];
588 if (YSTRUE == isSigned) {
589 if (32768 <= rawSignedValue) {
590 rawSignedValue -= 65536;
594 rawSignedValue -= 32768;
598 return rawSignedValue;
603 void YsWavFile::SetSignedValue(unsigned char *savePtr, int rawSignedValue)
607 if (rawSignedValue < -128) {
608 rawSignedValue = -128;
610 else if (127 < rawSignedValue) {
611 rawSignedValue = 127;
613 if (YSTRUE == isSigned) {
614 if (0 > rawSignedValue) {
615 rawSignedValue += 256;
617 *savePtr = (unsigned char) rawSignedValue;
620 rawSignedValue += 128;
621 *savePtr = (unsigned char) rawSignedValue;
625 if (-32768 > rawSignedValue) {
626 rawSignedValue = -32768;
628 else if (32767 < rawSignedValue) {
629 rawSignedValue = 32767;
632 if (YSTRUE == isSigned) {
633 if (0 > rawSignedValue) {
634 rawSignedValue += 65536;
638 rawSignedValue += 32768;
641 // Assume little endian (.WAV is supposed to use little endian).
642 savePtr[0] = (rawSignedValue & 255);
643 savePtr[1] = ((rawSignedValue >> 8) & 255);