Fix internal bug and change the design of ico-app-samplenavi
[profile/ivi/ico-uxf-homescreen-sample-apps.git] / ico-app-soundsample / src / soundsample_yswavfile.cpp
1 /*
2  * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
3  *
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
7  *
8  */
9 /**
10  * @brief   Sound Sample APP
11  *          Test use with which sound is sounded
12  *
13  * @date    Mar-04-2013
14  */
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <math.h>
19 #include "soundsample_yswavfile.h"
20
21 //#include "app_log.h"
22 #include "ico_apf_log.h"
23
24 YsWavFile::YsWavFile()
25 {
26     dat = NULL;
27     Initialize();
28 }
29
30 YsWavFile::~YsWavFile()
31 {
32     if (dat != NULL) {
33         delete[] dat;
34     }
35 }
36
37 void YsWavFile::Initialize(void)
38 {
39     if (dat != NULL) {
40         delete[] dat;
41         dat = NULL;
42     }
43
44     stereo = YSFALSE;
45     bit = 16;
46     rate = 44100;
47     sizeInBytes = 0;
48     isSigned = YSTRUE;
49 }
50
51 unsigned int YsWavFile::NTimeStep(void) const
52 {
53     return SizeInByte() / BytePerTimeStep();
54 }
55
56 YSBOOL YsWavFile::Stereo(void) const
57 {
58     return stereo;
59 }
60
61 unsigned int YsWavFile::BytePerTimeStep(void) const
62 {
63     unsigned int nChannel = (YSTRUE == stereo ? 2 : 1);
64     return nChannel * BytePerSample();
65 }
66
67 unsigned int YsWavFile::BitPerSample(void) const
68 {
69     return bit;
70 }
71
72 unsigned int YsWavFile::BytePerSample(void) const
73 {
74     return bit / 8;
75 }
76
77 unsigned int YsWavFile::PlayBackRate(void) const
78 {
79     return rate;
80 }
81
82 unsigned int YsWavFile::SizeInByte(void) const
83 {
84     return sizeInBytes;
85 }
86
87 YSBOOL YsWavFile::IsSigned(void) const
88 {
89     return isSigned;
90 }
91
92 const unsigned char *YsWavFile::DataPointer(void) const
93 {
94     return dat;
95 }
96
97 const unsigned char *YsWavFile::DataPointerAtTimeStep(unsigned int ts) const
98 {
99     return dat + ts * BytePerTimeStep();
100 }
101
102 static unsigned GetUnsigned(const unsigned char buf[])
103 {
104     return buf[0] + buf[1] * 0x100 + buf[2] * 0x10000 + buf[3] * 0x1000000;
105 }
106
107 static unsigned GetUnsignedShort(const unsigned char buf[])
108 {
109     return buf[0] + buf[1] * 0x100;
110 }
111
112
113
114 YSRESULT YsWavFile::LoadWav(const char fn[])
115 {
116     FILE *fp;
117
118     uim_debug("Loading %s", fn);
119
120     fp = fopen(fn, "rb");
121     if (fp != NULL) {
122         unsigned char buf[256];
123         unsigned int l;
124         unsigned int fSize, hdrSize, dataSize;
125
126         // Wave Header
127         unsigned short wFormatTag, nChannels;
128         unsigned nSamplesPerSec, nAvgBytesPerSec;
129         unsigned short nBlockAlign, wBitsPerSample, cbSize;
130
131
132         if (fread(buf, 1, 4, fp) != 4) {
133             uim_debug("Error in reading RIFF.");
134             goto ERREND;
135         }
136         if (strncmp((char *) buf, "RIFF", 4) != 0) {
137             uim_debug("Warning: RIFF not found.");
138         }
139
140
141         if (fread(buf, 1, 4, fp) != 4) {
142             uim_debug("Error in reading file size.");
143             goto ERREND;
144         }
145         fSize = GetUnsigned(buf);
146         uim_debug("File Size=%d", fSize + 8);
147
148         if (fread(buf, 1, 8, fp) != 8) {
149             uim_debug("Error in reading WAVEfmt.");
150             goto ERREND;
151         }
152         if (strncmp((char *) buf, "WAVEfmt", 7) != 0) {
153             uim_debug("Warning: WAVEfmt not found");
154         }
155
156
157         if (fread(buf, 1, 4, fp) != 4) {
158             uim_debug("Error in reading header size.");
159             goto ERREND;
160         }
161         hdrSize = GetUnsigned(buf);
162         uim_debug("Header Size=%d", hdrSize);
163
164
165         //    WORD  wFormatTag;
166         //    WORD  nChannels;
167         //    DWORD nSamplesPerSec;
168         //    DWORD nAvgBytesPerSec;
169         //    WORD  nBlockAlign;
170         //    WORD  wBitsPerSample;
171         //    WORD  cbSize;
172         if (fread(buf, 1, hdrSize, fp) != hdrSize) {
173             uim_debug("Error in reading header.");
174             goto ERREND;
175         }
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);
183
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);
191
192
193
194         while (1) {
195             if (fread(buf, 1, 4, fp) != 4) {
196                 uim_debug("Error while waiting for data.");
197                 goto ERREND;
198             }
199
200             if ((buf[0] == 'd' || buf[0] == 'D')
201                 && (buf[1] == 'a' || buf[1] == 'A') && (buf[2] == 't'
202                                                         || buf[2] == 'T')
203                 && (buf[3] == 'a' || buf[3] == 'A')) {
204                 break;
205             }
206             else {
207                 uim_debug("Skipping %c%c%c%c", buf[0], buf[1], buf[2],
208                             buf[3]);
209                 if (fread(buf, 1, 4, fp) != 4) {
210                     uim_debug("Error while skipping unknown block.");
211                     goto ERREND;
212                 }
213
214
215
216                 l = GetUnsigned(buf);
217                 if (fread(buf, 1, l, fp) != l) {
218                     uim_debug("Error while skipping unknown block.");
219                     goto ERREND;
220                 }
221             }
222         }
223
224
225         if (fread(buf, 1, 4, fp) != 4) {
226             uim_debug("Error in reading data size.");
227             goto ERREND;
228         }
229         dataSize = GetUnsigned(buf);
230         uim_debug("Data Size=%d (0x%x)", dataSize, dataSize);
231
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);
236         }
237
238         stereo = (nChannels == 2 ? YSTRUE : YSFALSE);
239         bit = wBitsPerSample;
240         sizeInBytes = dataSize;
241         rate = nSamplesPerSec;
242
243         if (wBitsPerSample == 8) {
244             isSigned = YSFALSE;
245         }
246         else {
247             isSigned = YSTRUE;
248         }
249
250         fclose(fp);
251         return YSOK;
252     }
253     return YSERR;
254
255   ERREND:
256     uim_debug("Err!");
257     if (fp != NULL) {
258         fclose(fp);
259     }
260     return YSERR;
261 }
262
263
264 YSRESULT YsWavFile::ConvertTo16Bit(void)
265 {
266     if (bit == 16) {
267         return YSOK;
268     }
269     else if (bit == 8) {
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];
276             }
277             delete[] dat;
278             dat = newDat;
279
280             sizeInBytes *= 2;
281             bit = 16;
282         }
283         return YSOK;
284     }
285     return YSERR;
286 }
287
288 YSRESULT YsWavFile::ConvertTo8Bit(void)
289 {
290     if (bit == 8) {
291         return YSOK;
292     }
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];
298         }
299         if (dat != NULL) {
300             delete[] dat;
301         }
302         dat = newDat;
303         bit = 8;
304         sizeInBytes /= 2;
305         return YSOK;
306     }
307     return YSERR;
308 }
309
310 YSRESULT YsWavFile::ConvertToStereo(void)
311 {
312     if (stereo == YSTRUE) {
313         return YSOK;
314     }
315     else {
316         if (bit == 8) {
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];
322             }
323             if (dat != NULL) {
324                 delete[] dat;
325             }
326             dat = newDat;
327             stereo = YSTRUE;
328             sizeInBytes *= 2;
329             return YSOK;
330         }
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];
339             }
340             if (dat != NULL) {
341                 delete[] dat;
342             }
343             dat = newDat;
344             stereo = YSTRUE;
345             sizeInBytes *= 2;
346             return YSOK;
347         }
348     }
349     return YSERR;
350 }
351
352 //YSRESULT YsWavFile::Resample(int newRate)
353 YSRESULT YsWavFile::Resample(unsigned int newRate)
354 {
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;
360
361         const size_t newNTimeStep = curNTimeStep * newRate / rate;
362         const size_t newSize = newNTimeStep * bytePerTimeStep;
363
364         unsigned char *newDat;
365         newDat = (0 < newSize ? new unsigned char[newSize] : NULL);
366
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;
374
375                 for (size_t ch = 0; ch < nChannel; ++ch) {
376                     if (curNTimeStep - 1 <= oldTimeStep) {
377                         const int value =
378                             GetSignedValue(curNTimeStep - 1, ch);
379                         SetSignedValue(newTimeStepPtr + bytePerSample * ch,
380                                        value);
381                     }
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)
387                         };
388                         const int newValue = (int)
389                             (value[0] * (1.0 - param) + value[1] * param);
390                         SetSignedValue(newTimeStepPtr + bytePerSample * ch,
391                                        newValue);
392                     }
393                     else {
394                         const double v[4] = {
395                             // At x=-1.0
396                             (double) GetSignedValue(oldTimeStep - 1, ch),
397                             // At x= 0.0
398                             (double) GetSignedValue(oldTimeStep, ch),
399                             // At x= 1.0
400                             (double) GetSignedValue(oldTimeStep + 1, ch),
401                             // At x= 2.0
402                             (double) GetSignedValue(oldTimeStep + 2, ch)
403                         };
404
405                         // Cubic interpolation.  Linear didn't work well.
406                         // axxx+bxx+cx+d=e
407                         // x=-1  -> -a+b-c+d=v0   (A)
408                         // x= 0  ->        d=v1   (B)
409                         // x= 1  ->  a+b+c+d=v2   (C)
410                         // x= 2  -> 8a+4b+2c+d=v3 (D)
411                         //
412                         // (B) =>  d=v1;
413                         // (A)+(C) => 2b+2d=v0+v2  => b=(v0+v2-2d)/2
414                         //
415                         // (D)-2*(B) =>  6a+2b-d=v3-2*v2
416                         //           =>  a=(v3-2*v2-2b+d)/6
417
418                         const double d = v[1];
419                         const double b = (v[0] + v[2] - 2.0 * d) / 2.0;
420                         const double a =
421                             (v[3] - 2.0 * v[2] - 2.0 * b + d) / 6.0;
422                         const double c = v[2] - a - b - d;
423
424                         double newValue = a * param * param * param
425                             + b * param * param + c * param + d;
426                         SetSignedValue(newTimeStepPtr + bytePerSample * ch,
427                                        (int) newValue);
428                     }
429                 }
430             }
431         }
432
433         rate = newRate;
434         if (dat != NULL) {
435             delete[] dat;
436         }
437         dat = newDat;
438         sizeInBytes = newSize;
439     }
440     return YSOK;
441 }
442
443 YSRESULT YsWavFile::ConvertToMono(void)
444 {
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;
449
450         const size_t newSize = nTimeStep * bytePerSample;
451
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++) {
456                 const int newValue =
457                     (GetSignedValue(ts, 0) + GetSignedValue(ts, 1)) / 2;
458                 unsigned char *const newTimeStepPtr =
459                     newDat + ts * bytePerSample;
460                 SetSignedValue(newTimeStepPtr, newValue);
461             }
462
463             if (dat != NULL) {
464                 delete[] dat;
465             }
466             dat = newDat;
467             sizeInBytes = newSize;
468             stereo = YSFALSE;
469
470             return YSOK;
471         }
472     }
473     return YSERR;
474 }
475
476 YSRESULT YsWavFile::ConvertToSigned(void)
477 {
478     if (isSigned == YSTRUE) {
479         return YSOK;
480     }
481     else {
482         if (bit == 8) {
483 //          for (int i = 0; i < sizeInBytes; i++)
484             for (unsigned int i = 0; i < sizeInBytes; i++) {
485                 dat[i] -= 128;
486             }
487         }
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) {
491                 int d;
492                 d = dat[i] + dat[i + 1] * 256;
493                 d -= 32768;
494                 dat[i] = d & 255;
495                 dat[i + 1] = (d >> 8) & 255;
496             }
497         }
498         isSigned = YSTRUE;
499     }
500     return YSOK;
501 }
502
503 YSRESULT YsWavFile::ConvertToUnsigned(void)
504 {
505     if (isSigned != YSTRUE) {
506         return YSOK;
507     }
508     else {
509         if (bit == 8) {
510 //          for (int i = 0; i < sizeInBytes; i++)
511             for (unsigned int i = 0; i < sizeInBytes; i++) {
512                 dat[i] += 128;
513             }
514         }
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;
519                 if (d >= 32768) {
520                     d -= 65536;
521                 }
522                 d += 32768;
523                 dat[i] = d & 255;
524                 dat[i + 1] = (d >> 8) & 255;
525             }
526         }
527         isSigned = YSFALSE;
528     }
529     return YSOK;
530 }
531
532 //int main(int ac,char *av[])
533 //{
534 //  YsWavFile test;
535 //  test.LoadWav(av[1]);
536 //  return 0;
537 //}
538
539 int YsWavFile::GetNumChannel(void) const
540 {
541     return (YSTRUE == stereo ? 2 : 1);
542 }
543
544 int YsWavFile::GetNumSample(void) const
545 {
546     return sizeInBytes * 8 / bit;
547 }
548
549 int YsWavFile::GetNumSamplePerChannel(void) const
550 {
551     return GetNumSample() / GetNumChannel();
552 }
553
554 size_t YsWavFile::GetUnitSize(void) const
555 {
556     return BytePerSample() * GetNumChannel();
557 }
558
559 size_t YsWavFile::GetSamplePosition(int atIndex) const
560 {
561     return atIndex * GetNumChannel() * (bit / 8);
562 }
563
564 int YsWavFile::GetSignedValue(int atTimeStep, int channel) const
565 {
566     const size_t sampleIdx = GetSamplePosition(atTimeStep);
567     const size_t unitSize = GetUnitSize();
568
569     if ((sampleIdx + unitSize <= sizeInBytes) &&
570         (0 <= channel) && (channel < GetNumChannel())) {
571         int rawSignedValue = 0;
572         size_t offset = sampleIdx + channel * BytePerSample();
573         switch (BitPerSample()) {
574         case 8:
575             if (YSTRUE == isSigned) {
576                 rawSignedValue = dat[offset];
577                 if (128 <= rawSignedValue) {
578                     rawSignedValue -= 256;
579                 }
580             }
581             else {
582                 rawSignedValue = dat[offset] - 128;
583             }
584             break;
585         case 16:
586             // Assume little endian
587             rawSignedValue = dat[offset] + 256 * dat[offset + 1];
588             if (YSTRUE == isSigned) {
589                 if (32768 <= rawSignedValue) {
590                     rawSignedValue -= 65536;
591                 }
592             }
593             else {
594                 rawSignedValue -= 32768;
595             }
596             break;
597         }
598         return rawSignedValue;
599     }
600     return 0;
601 }
602
603 void YsWavFile::SetSignedValue(unsigned char *savePtr, int rawSignedValue)
604 {
605     switch (bit) {
606     case 8:
607         if (rawSignedValue < -128) {
608             rawSignedValue = -128;
609         }
610         else if (127 < rawSignedValue) {
611             rawSignedValue = 127;
612         }
613         if (YSTRUE == isSigned) {
614             if (0 > rawSignedValue) {
615                 rawSignedValue += 256;
616             }
617             *savePtr = (unsigned char) rawSignedValue;
618         }
619         else {
620             rawSignedValue += 128;
621             *savePtr = (unsigned char) rawSignedValue;
622         }
623         break;
624     case 16:
625         if (-32768 > rawSignedValue) {
626             rawSignedValue = -32768;
627         }
628         else if (32767 < rawSignedValue) {
629             rawSignedValue = 32767;
630         }
631
632         if (YSTRUE == isSigned) {
633             if (0 > rawSignedValue) {
634                 rawSignedValue += 65536;
635             }
636         }
637         else {
638             rawSignedValue += 32768;
639         }
640
641         // Assume little endian (.WAV is supposed to use little endian).
642         savePtr[0] = (rawSignedValue & 255);
643         savePtr[1] = ((rawSignedValue >> 8) & 255);
644         break;
645     }
646 }