GEAudioBuffer.cpp 12 KB

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