AudioBuffer.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*
  2. * Copyright (c) 2011 Nokia Corporation.
  3. */
  4. /**
  5. *
  6. * GE::GA AudioBuffer functionality
  7. * tuomo.hirvonen@digia.com
  8. *
  9. */
  10. #include <stdio.h>
  11. #include <memory.h>
  12. #include <math.h>
  13. #include "AudioBuffer.h"
  14. using namespace GF;
  15. #pragma pack(1)
  16. // size = 44?
  17. struct SWavHeader {
  18. char chunkID[4];
  19. unsigned int chunkSize;
  20. char format[4];
  21. unsigned char subchunk1id[4];
  22. unsigned int subchunk1size;
  23. unsigned short audioFormat;
  24. unsigned short nofChannels;
  25. unsigned int sampleRate;
  26. unsigned int byteRate;
  27. unsigned short blockAlign;
  28. unsigned short bitsPerSample;
  29. unsigned char subchunk2id[4];
  30. unsigned int subchunk2size;
  31. };
  32. #pragma pack()
  33. AudioBuffer::AudioBuffer() {
  34. m_data = 0;
  35. m_dataLength = 0;
  36. m_sampleFunction = 0;
  37. };
  38. AudioBuffer::~AudioBuffer() {
  39. reallocate(0);
  40. }
  41. void AudioBuffer::reallocate( int length ) {
  42. if (m_data) delete [] ((char*)m_data);
  43. m_dataLength = length;
  44. if (m_dataLength>0) {
  45. m_data = new char[ m_dataLength ];
  46. } else m_data = 0;
  47. };
  48. int readWrapper( void *target, const int length, const void *sbuf, const int sbuflen, int &pos )
  49. {
  50. memcpy( target, ((const char*)sbuf)+pos, length );
  51. pos+=length;
  52. return length;
  53. }
  54. AudioBuffer *AudioBuffer::loadWav( const void *d, unsigned int dlength )
  55. {
  56. // read the header.
  57. SWavHeader header;
  58. int p=0;
  59. readWrapper( &header.chunkID, 44, d,dlength, p);
  60. // Sanity check
  61. if (header.chunkID[0]!='R' || header.chunkID[1]!='I' || header.chunkID[2]!='F' || header.chunkID[3]!='F') return 0; // incorrect header
  62. if (header.format[0]!='W' || header.format[1]!='A' || header.format[2]!='V' || header.format[3]!='E') return 0; // incorrect header
  63. if (header.subchunk1id[0]!='f' || header.subchunk1id[1]!='m' || header.subchunk1id[2]!='t' || header.subchunk1id[3]!=' ') return 0; // incorrect header
  64. if (header.subchunk2id[0]!='d' || header.subchunk2id[1]!='a' || header.subchunk2id[2]!='t' || header.subchunk2id[3]!='a') return 0; // incorrect header
  65. // the data follows.
  66. if (header.subchunk2size<1) return 0;
  67. AudioBuffer *rval = new AudioBuffer;
  68. rval->m_nofChannels = header.nofChannels;
  69. rval->m_bitsPerSample = header.bitsPerSample;
  70. rval->m_samplesPerSec = header.sampleRate;
  71. rval->m_signedData = 0; // where to know this?
  72. rval->reallocate( header.subchunk2size );
  73. //fread( rval->m_data, 1, header.subchunk2size, wavFile );
  74. readWrapper( rval->m_data, header.subchunk2size, d,dlength, p);
  75. // choose a good sampling function.
  76. rval->m_sampleFunction = 0;
  77. if (rval->m_nofChannels==1) {
  78. if (rval->m_bitsPerSample == 8) rval->m_sampleFunction = sampleFunction8bitMono;
  79. if (rval->m_bitsPerSample == 16) rval->m_sampleFunction = sampleFunction16bitMono;
  80. } else {
  81. if (rval->m_bitsPerSample == 8) rval->m_sampleFunction = sampleFunction8bitStereo;
  82. if (rval->m_bitsPerSample == 16) rval->m_sampleFunction = sampleFunction16bitStereo;
  83. }
  84. return rval;
  85. }
  86. AudioBuffer* AudioBuffer::loadWav( const char *fileName) {
  87. FILE *f = fopen( fileName, "rb");
  88. if (f==0) return 0;
  89. AudioBuffer *rval = loadWav(f);
  90. fclose(f);
  91. return rval;
  92. };
  93. AudioBuffer* AudioBuffer::loadWav( FILE *wavFile ) {
  94. fseek(wavFile, 0L, SEEK_END);
  95. int fileLength = ftell(wavFile);
  96. fseek(wavFile, 0L, SEEK_SET);
  97. char *fileData = new char[ fileLength ];
  98. fread( fileData, fileLength, 1, wavFile );
  99. AudioBuffer *rval = loadWav( fileData, fileLength );
  100. delete [] fileData;
  101. return rval;
  102. /*
  103. // DIRECT FILE READING.. COMMENTED FOR NOW.
  104. // read the header.
  105. SWavHeader header;
  106. fread( header.chunkID, 4, 1, wavFile );
  107. if (header.chunkID[0]!='R' || header.chunkID[1]!='I' || header.chunkID[2]!='F' || header.chunkID[3]!='F') return 0; // incorrect header
  108. fread( &header.chunkSize, 4, 1, wavFile );
  109. fread( header.format, 4, 1, wavFile );
  110. if (header.format[0]!='W' || header.format[1]!='A' || header.format[2]!='V' || header.format[3]!='E') return 0; // incorrect header
  111. fread( header.subchunk1id, 4, 1, wavFile );
  112. if (header.subchunk1id[0]!='f' || header.subchunk1id[1]!='m' || header.subchunk1id[2]!='t' || header.subchunk1id[3]!=' ') return 0; // incorrect header
  113. fread( &header.subchunk1size, 4, 1, wavFile );
  114. fread( &header.audioFormat, 2, 1, wavFile );
  115. fread( &header.nofChannels, 2, 1, wavFile );
  116. fread( &header.sampleRate, 4, 1, wavFile );
  117. fread( &header.byteRate, 4, 1, wavFile );
  118. fread( &header.blockAlign, 2, 1, wavFile );
  119. fread( &header.bitsPerSample, 2, 1, wavFile );
  120. fread( header.subchunk2id, 4, 1, wavFile );
  121. if (header.subchunk2id[0]!='d' || header.subchunk2id[1]!='a' || header.subchunk2id[2]!='t' || header.subchunk2id[3]!='a') return 0; // incorrect header
  122. fread( &header.subchunk2size, 4, 1, wavFile );
  123. // the data follows.
  124. if (header.subchunk2size<1) return 0;
  125. AudioBuffer *rval = new AudioBuffer;
  126. rval->m_nofChannels = header.nofChannels;
  127. rval->m_bitsPerSample = header.bitsPerSample;
  128. rval->m_samplesPerSec = header.sampleRate;
  129. rval->m_signedData = 0; // where to know this?
  130. rval->reallocate( header.subchunk2size );
  131. fread( rval->m_data, 1, header.subchunk2size, wavFile );
  132. // choose a good sampling function.
  133. rval->m_sampleFunction = 0;
  134. if (rval->m_nofChannels==1) {
  135. if (rval->m_bitsPerSample == 8) rval->m_sampleFunction = sampleFunction8bitMono;
  136. if (rval->m_bitsPerSample == 16) rval->m_sampleFunction = sampleFunction16bitMono;
  137. } else {
  138. if (rval->m_bitsPerSample == 8) rval->m_sampleFunction = sampleFunction8bitStereo;
  139. if (rval->m_bitsPerSample == 16) rval->m_sampleFunction = sampleFunction16bitStereo;
  140. }
  141. return rval;
  142. */
  143. };
  144. AUDIO_SAMPLE_TYPE AudioBuffer::sampleFunction8bitMono( AudioBuffer *abuffer, int pos, int channel ) {
  145. return (AUDIO_SAMPLE_TYPE)(((unsigned char*)(abuffer->m_data))[pos]-128)<<8;
  146. };
  147. AUDIO_SAMPLE_TYPE AudioBuffer::sampleFunction16bitMono( AudioBuffer *abuffer, int pos, int channel ) {
  148. return (AUDIO_SAMPLE_TYPE)(((short*)(abuffer->m_data))[pos]);
  149. };
  150. AUDIO_SAMPLE_TYPE AudioBuffer::sampleFunction8bitStereo( AudioBuffer *abuffer, int pos, int channel ) {
  151. return ((AUDIO_SAMPLE_TYPE)(((char*)(abuffer->m_data))[pos*abuffer->m_nofChannels + channel])<<8);
  152. };
  153. AUDIO_SAMPLE_TYPE AudioBuffer::sampleFunction16bitStereo( AudioBuffer *abuffer, int pos, int channel ) {
  154. return (AUDIO_SAMPLE_TYPE)(((short*)(abuffer->m_data))[pos*abuffer->m_nofChannels + channel]);
  155. };
  156. AudioBufferPlayInstance *AudioBuffer::playWithMixer( AudioMixer &mixer ) {
  157. AudioBufferPlayInstance *i = (AudioBufferPlayInstance*)mixer.addAudioSource( new AudioBufferPlayInstance( this ));
  158. return i;
  159. };
  160. AudioBufferPlayInstance::AudioBufferPlayInstance() {
  161. m_fixedPos = 0;
  162. m_fixedInc = 0;
  163. m_buffer = 0;
  164. m_fixedLeftVolume = 4096;
  165. m_fixedRightVolume = 4096;
  166. m_destroyWhenFinished = true;
  167. m_finished = false;
  168. };
  169. AudioBufferPlayInstance::AudioBufferPlayInstance( AudioBuffer *startPlaying ) {
  170. m_fixedPos = 0;
  171. m_fixedInc = 0;
  172. m_fixedLeftVolume = 4096;
  173. m_fixedRightVolume = 4096;
  174. m_destroyWhenFinished = true;
  175. m_finished = false;
  176. playBuffer( startPlaying, 1.0f, 1.0f );
  177. };
  178. void AudioBufferPlayInstance::playBuffer( AudioBuffer *startPlaying, float volume, float speed, int loopTimes ) {
  179. m_buffer = startPlaying;
  180. m_fixedLeftVolume = (int)(4096.0f*volume);
  181. m_fixedRightVolume = m_fixedLeftVolume;
  182. m_fixedPos = 0;
  183. //m_fixedInc = ( startPlaying->getSamplesPerSec() * (int)(4096.0f*speed)) / AUDIO_FREQUENCY;
  184. setSpeed( speed );
  185. m_loopTimes = loopTimes;
  186. };
  187. AudioBufferPlayInstance::~AudioBufferPlayInstance() {
  188. };
  189. void AudioBufferPlayInstance::stop() {
  190. m_buffer = 0;
  191. m_finished = true;
  192. };
  193. void AudioBufferPlayInstance::setSpeed( float speed ) {
  194. if (!m_buffer) return;
  195. m_fixedInc = (int)( ((float)m_buffer->getSamplesPerSec() * 4096.0f*speed) / (float)AUDIO_FREQUENCY );
  196. };
  197. void AudioBufferPlayInstance::setLeftVolume( float vol ) {
  198. m_fixedLeftVolume = (int)(4096.0f*vol);
  199. };
  200. void AudioBufferPlayInstance::setRightVolume( float vol ) {
  201. m_fixedRightVolume = (int)(4096.0f*vol);
  202. };
  203. bool AudioBufferPlayInstance::canBeDestroyed() {
  204. if (m_finished==true &&
  205. m_destroyWhenFinished==true) return true; else return false;
  206. };
  207. // doesnt do any bound-checking Must be checked before called.
  208. int AudioBufferPlayInstance::mixBlock( AudioBuffer *buffer, AUDIO_SAMPLE_TYPE *target, int samplesToMix ) {
  209. //qDebug() << "AudioBufferPlayInstance::mixBlock" << samplesToMix;
  210. SAMPLE_FUNCTION_TYPE sampleFunction = buffer->getSampleFunction();
  211. if (!sampleFunction) return 0; // unsupported sampletype
  212. AUDIO_SAMPLE_TYPE *t_target = target+samplesToMix*AUDIO_CHANNELS;
  213. int sourcepos;
  214. //int tempCounter = 0;
  215. if (buffer->getNofChannels() == 2) { // stereo
  216. while (target!=t_target) {
  217. sourcepos = m_fixedPos>>12;
  218. //target[0] = (((((sampleFunction)( buffer, sourcepos, 0) * (4096-(m_fixedPos&4095)) + (sampleFunction)( m_buffer, sourcepos+1, 0) * (m_fixedPos&4095) ) >> 12) * m_fixedLeftVolume) >> 12);
  219. //target[1] = (((((sampleFunction)( buffer, sourcepos, 1) * (4096-(m_fixedPos&4095)) + (sampleFunction)( m_buffer, sourcepos+1, 1) * (m_fixedPos&4095) ) >> 12) * m_fixedRightVolume) >> 12);
  220. // no resampling here
  221. target[0] = (((sampleFunction)( buffer, sourcepos, 0) * m_fixedLeftVolume) >> 12);
  222. target[1] = (((sampleFunction)( buffer, sourcepos, 1) * m_fixedRightVolume) >> 12);
  223. m_fixedPos+=m_fixedInc;
  224. target+=2;
  225. //tempCounter++;
  226. };
  227. } else { // mono
  228. int temp;
  229. while (target!=t_target) {
  230. sourcepos = m_fixedPos>>12;
  231. //temp = (((sampleFunction)( m_buffer, sourcepos, 0 ) * (4096-(m_fixedPos&4095)) + (sampleFunction)( m_buffer, sourcepos+1, 0 ) * (m_fixedPos&4095) ) >> 12);
  232. temp = (sampleFunction)( buffer, sourcepos, 0);
  233. target[0] = ((temp*m_fixedLeftVolume)>>12);
  234. target[1] = ((temp*m_fixedRightVolume)>>12);
  235. m_fixedPos+=m_fixedInc;
  236. target+=2;
  237. //tempCounter++;
  238. };
  239. };
  240. return samplesToMix;
  241. };
  242. int AudioBufferPlayInstance::pullAudio( AUDIO_SAMPLE_TYPE *target, int sampleCount ) {
  243. //qDebug() << "AudioBufferPlayInstance::pullAudio" << sampleCount;
  244. if (!m_buffer) return 0; // no sample associated to mix..
  245. AudioBuffer *buffer = m_buffer; // use this for now
  246. int channelLength = ((buffer->getDataLength()) / (buffer->getNofChannels()*buffer->getBytesPerSample()))-2;
  247. int samplesToWritePerChannel = sampleCount/AUDIO_CHANNELS;
  248. int amount;
  249. int totalMixed = 0;
  250. while (samplesToWritePerChannel>0) {
  251. int samplesLeft = channelLength - (m_fixedPos>>12);
  252. int maxMixAmount = (int)(((long long int)(samplesLeft)<<12) / m_fixedInc ); // This is how much we can mix at least
  253. //int maxMixAmount = (int)((float)samplesLeft / ((float)m_fixedInc/4096.0f));
  254. //if (maxMixAmount<1) maxMixAmount = 1; // NOTE, THIS MIGHT CAUSE PROBLEMS. NEEDS CHECKING
  255. if (maxMixAmount>samplesToWritePerChannel) {
  256. maxMixAmount=samplesToWritePerChannel;
  257. }
  258. if (maxMixAmount>0) {
  259. amount=mixBlock(buffer, target+totalMixed*2, maxMixAmount );
  260. if (amount==0)
  261. {
  262. break; // an error occured
  263. }
  264. totalMixed+=amount;
  265. } else {
  266. amount = 0;
  267. m_fixedPos = channelLength<<12;
  268. }
  269. // sample is ended,.. check the looping variables and see what to do.
  270. if ((m_fixedPos>>12)>=channelLength) {
  271. m_fixedPos -= (channelLength<<12);
  272. if (m_loopTimes>0) m_loopTimes--;
  273. if (m_loopTimes==0) {
  274. stop();
  275. return totalMixed;
  276. }
  277. }
  278. samplesToWritePerChannel-=amount;
  279. if (samplesToWritePerChannel<1) break;
  280. };
  281. return totalMixed*2;
  282. };