GEAudioBuffer.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /**
  2. * Copyright (c) 2011 Nokia Corporation.
  3. *
  4. * Part of the Qt GameEnabler.
  5. */
  6. #include "GEAudioBuffer.h"
  7. #include <math.h>
  8. #include <QFile>
  9. #include "GEAudioBufferPlayInstance.h"
  10. #include "GEAudioMixer.h"
  11. #include "trace.h"
  12. using namespace GE;
  13. /*!
  14. Header for wav data
  15. */
  16. struct SWavHeader {
  17. char chunkID[4];
  18. unsigned int chunkSize;
  19. char format[4];
  20. unsigned char subchunk1id[4];
  21. unsigned int subchunk1size;
  22. unsigned short audioFormat;
  23. unsigned short nofChannels;
  24. unsigned int sampleRate;
  25. unsigned int byteRate;
  26. unsigned short blockAlign;
  27. unsigned short bitsPerSample;
  28. unsigned char subchunk2id[4];
  29. unsigned int subchunk2size;
  30. };
  31. /*!
  32. * \class AudioBuffer
  33. * \brief A class to hold audio information (a buffer).
  34. */
  35. /*!
  36. Constructor.
  37. */
  38. AudioBuffer::AudioBuffer(QObject *parent /* = 0 */)
  39. : QObject(parent),
  40. m_sampleFunction(0),
  41. m_data(0),
  42. m_dataLength(0),
  43. m_nofChannels(0),
  44. m_bitsPerSample(0),
  45. m_signedData(false),
  46. m_samplesPerSec(0)
  47. {
  48. }
  49. /*!
  50. Destructor.
  51. */
  52. AudioBuffer::~AudioBuffer()
  53. {
  54. // Deallocate the data.
  55. reallocate(0);
  56. }
  57. /*!
  58. (Re)allocates the audio buffer according to \a length.
  59. */
  60. void AudioBuffer::reallocate(int length)
  61. {
  62. if (m_data) {
  63. delete [] ((char*)m_data);
  64. }
  65. m_dataLength = length;
  66. if (m_dataLength > 0) {
  67. m_data = new char[m_dataLength];
  68. }
  69. else {
  70. m_data = 0;
  71. }
  72. }
  73. /*!
  74. Loads a .wav file from file with \a fileName. Note that this method can be
  75. used for loading .wav from Qt resources as well. If \a parent is given, it
  76. is set as the parent of the constructed buffer.
  77. Returns a new buffer if successful, NULL otherwise.
  78. */
  79. AudioBuffer *AudioBuffer::loadWav(QString fileName, QObject *parent /* = 0 */)
  80. {
  81. QFile wavFile(fileName);
  82. if (wavFile.open(QIODevice::ReadOnly)) {
  83. AudioBuffer *buffer = loadWav(wavFile, parent);
  84. if (!buffer) {
  85. DEBUG_INFO("Failed to load data from " << fileName << "!");
  86. }
  87. wavFile.close();
  88. return buffer;
  89. }
  90. DEBUG_INFO("Failed to open " << fileName << ": " << wavFile.errorString());
  91. return 0;
  92. }
  93. /*!
  94. Protected method, called from AudioBuffer::loadWav(QString, QObject*).
  95. Loads a .wav file from a preopened \a wavFile. If \a parent is given, it is
  96. set as the parent of the constructed buffer.
  97. Returns a new buffer if successful, NULL otherwise.
  98. */
  99. AudioBuffer *AudioBuffer::loadWav(QFile &wavFile, QObject *parent /* = 0 */)
  100. {
  101. if (!wavFile.isOpen()) {
  102. // The file is not open!
  103. DEBUG_INFO("The given file must be opened before calling this method!");
  104. return 0;
  105. }
  106. SWavHeader header;
  107. wavFile.read(header.chunkID, 4);
  108. if (header.chunkID[0] != 'R' || header.chunkID[1] != 'I' ||
  109. header.chunkID[2] != 'F' || header.chunkID[3] != 'F') {
  110. // Incorrect header
  111. return 0;
  112. }
  113. wavFile.read((char*)&header.chunkSize, 4);
  114. wavFile.read((char*)&header.format, 4);
  115. if (header.format[0] != 'W' || header.format[1] != 'A' ||
  116. header.format[2] != 'V' || header.format[3] != 'E') {
  117. // Incorrect header
  118. return 0;
  119. }
  120. wavFile.read((char*)&header.subchunk1id, 4);
  121. if (header.subchunk1id[0] != 'f' || header.subchunk1id[1] != 'm' ||
  122. header.subchunk1id[2] != 't' || header.subchunk1id[3] != ' ') {
  123. // Incorrect header
  124. return 0;
  125. }
  126. wavFile.read((char*)&header.subchunk1size, 4);
  127. wavFile.read((char*)&header.audioFormat, 2);
  128. wavFile.read((char*)&header.nofChannels, 2);
  129. wavFile.read((char*)&header.sampleRate, 4);
  130. wavFile.read((char*)&header.byteRate, 4);
  131. wavFile.read((char*)&header.blockAlign, 2);
  132. wavFile.read((char*)&header.bitsPerSample, 2);
  133. while (1) {
  134. if (wavFile.read((char*)&header.subchunk2id, 4) != 4)
  135. return 0;
  136. if (wavFile.read((char*)&header.subchunk2size, 4) != 4)
  137. return 0;
  138. if (header.subchunk2id[0] == 'd' && header.subchunk2id[1] == 'a' &&
  139. header.subchunk2id[2] == 't' && header.subchunk2id[3] == 'a') {
  140. // Found the data chunk.
  141. break;
  142. }
  143. // This was not the data-chunk. Skip it.
  144. if (header.subchunk2size < 1) {
  145. // Error in file!
  146. return 0;
  147. }
  148. char *unused = new char[header.subchunk2size];
  149. wavFile.read(unused, header.subchunk2size);
  150. delete [] unused;
  151. }
  152. // The data follows.
  153. if (header.subchunk2size < 1)
  154. return 0;
  155. // Construct the buffer.
  156. AudioBuffer *buffer = new AudioBuffer(parent);
  157. buffer->m_nofChannels = header.nofChannels;
  158. buffer->m_bitsPerSample = header.bitsPerSample;
  159. buffer->m_samplesPerSec = header.sampleRate;
  160. buffer->m_signedData = 0; // Where to look for this?
  161. buffer->reallocate(header.subchunk2size);
  162. wavFile.read((char*)buffer->m_data, header.subchunk2size);
  163. // Select a good sampling function.
  164. if (!setSampleFunction(*buffer)) {
  165. // Failed to resolve the sample function!
  166. delete buffer;
  167. return 0;
  168. }
  169. return buffer;
  170. }
  171. /*!
  172. Loads a .wav file from a preopened file handle, \a wavFile. If \a parent is
  173. given, it is set as the parent of the constructed buffer.
  174. Returns a new buffer if successful, NULL otherwise.
  175. */
  176. AudioBuffer *AudioBuffer::loadWav(FILE *wavFile, QObject *parent /* = 0 */)
  177. {
  178. if (!wavFile) {
  179. // Invalid file handle!
  180. return 0;
  181. }
  182. // Read the header.
  183. SWavHeader header;
  184. fread(header.chunkID, 4, 1, wavFile);
  185. if (header.chunkID[0] != 'R' || header.chunkID[1] != 'I' ||
  186. header.chunkID[2] != 'F' || header.chunkID[3] != 'F') {
  187. // Incorrect header
  188. return 0;
  189. }
  190. fread(&header.chunkSize, 4, 1, wavFile);
  191. fread(header.format, 4, 1, wavFile);
  192. if (header.format[0] != 'W' || header.format[1] != 'A' ||
  193. header.format[2] != 'V' || header.format[3] != 'E') {
  194. // Incorrect header
  195. return 0;
  196. }
  197. fread(header.subchunk1id, 4, 1, wavFile);
  198. if (header.subchunk1id[0] != 'f' || header.subchunk1id[1] != 'm' ||
  199. header.subchunk1id[2] != 't' || header.subchunk1id[3] != ' ') {
  200. // Incorrect header
  201. return 0;
  202. }
  203. fread(&header.subchunk1size, 4, 1, wavFile);
  204. fread(&header.audioFormat, 2, 1, wavFile);
  205. fread(&header.nofChannels, 2, 1, wavFile);
  206. fread(&header.sampleRate, 4, 1, wavFile);
  207. fread(&header.byteRate, 4, 1, wavFile);
  208. fread(&header.blockAlign, 2, 1, wavFile);
  209. fread(&header.bitsPerSample, 2, 1, wavFile);
  210. fread(header.subchunk2id, 4, 1, wavFile);
  211. if (header.subchunk2id[0] != 'd' || header.subchunk2id[1] != 'a' ||
  212. header.subchunk2id[2] != 't' || header.subchunk2id[3] != 'a') {
  213. // Incorrect header
  214. return 0;
  215. }
  216. fread(&header.subchunk2size, 4, 1, wavFile);
  217. // The data follows.
  218. if (header.subchunk2size < 1)
  219. return 0;
  220. AudioBuffer *buffer = new AudioBuffer(parent);
  221. buffer->m_nofChannels = header.nofChannels;
  222. buffer->m_bitsPerSample = header.bitsPerSample;
  223. buffer->m_samplesPerSec = header.sampleRate;
  224. buffer->m_signedData = 0; // Where to look for this?
  225. buffer->reallocate(header.subchunk2size);
  226. fread(buffer->m_data, 1, header.subchunk2size, wavFile);
  227. // Select a good sampling function.
  228. if (!setSampleFunction(*buffer)) {
  229. // Failed to select the sampling function!
  230. delete buffer;
  231. return 0;
  232. }
  233. return buffer;
  234. }
  235. // Mix to mono versions.
  236. AUDIO_SAMPLE_TYPE AudioBuffer::sampleFunction8bitMono(AudioBuffer *buffer,
  237. int pos,
  238. int channel)
  239. {
  240. Q_UNUSED(channel);
  241. return (AUDIO_SAMPLE_TYPE)(((quint8*)(buffer->m_data))[pos] - 128) << 8;
  242. }
  243. AUDIO_SAMPLE_TYPE AudioBuffer::sampleFunction16bitMono(AudioBuffer *buffer,
  244. int pos,
  245. int channel)
  246. {
  247. Q_UNUSED(channel);
  248. return (AUDIO_SAMPLE_TYPE)(((quint16*)(buffer->m_data))[pos]);
  249. }
  250. AUDIO_SAMPLE_TYPE AudioBuffer::sampleFunction32bitMono(AudioBuffer *buffer,
  251. int pos,
  252. int channel)
  253. {
  254. Q_UNUSED(channel); // To prevent compiler warnings.
  255. return (((float*)(buffer->m_data))[pos * buffer->m_nofChannels]) * 65536.0f / 2.0f;
  256. }
  257. // Mix to stereo versions.
  258. AUDIO_SAMPLE_TYPE AudioBuffer::sampleFunction8bitStereo(AudioBuffer *buffer,
  259. int pos,
  260. int channel)
  261. {
  262. return ((AUDIO_SAMPLE_TYPE)
  263. (((quint8*)(buffer->m_data))[pos * buffer->m_nofChannels + channel]) << 8);
  264. }
  265. AUDIO_SAMPLE_TYPE AudioBuffer::sampleFunction16bitStereo(AudioBuffer *buffer,
  266. int pos,
  267. int channel)
  268. {
  269. return (AUDIO_SAMPLE_TYPE)
  270. (((quint16*)(buffer->m_data))[pos * buffer->m_nofChannels + channel]);
  271. }
  272. AUDIO_SAMPLE_TYPE AudioBuffer::sampleFunction32bitStereo(AudioBuffer *buffer,
  273. int pos,
  274. int channel)
  275. {
  276. return (((float*)(buffer->m_data))[pos * buffer->m_nofChannels +
  277. channel]) * 65536.0f / 2.0f;
  278. }
  279. /*!
  280. Constructs a new play instance and sets it as an audio source for \a mixer.
  281. Note that the mixer takes ownership of the constructed instance.
  282. Returns the constructed instance or NULL in case the mixer refused to add
  283. the instance.
  284. */
  285. AudioBufferPlayInstance *AudioBuffer::playWithMixer(AudioMixer &mixer)
  286. {
  287. AudioBufferPlayInstance *instance = new AudioBufferPlayInstance(this);
  288. if (!mixer.addAudioSource(instance)) {
  289. DEBUG_INFO("Failed to add the new audio source to mixer!");
  290. delete instance;
  291. return NULL;
  292. }
  293. return instance;
  294. }
  295. /*!
  296. Sets an appropriate sample function for \a buffer depending on the number of
  297. channels and the bit rate.
  298. Returns true if successful, false otherwise.
  299. */
  300. bool AudioBuffer::setSampleFunction(AudioBuffer &buffer)
  301. {
  302. buffer.m_sampleFunction = 0;
  303. if (buffer.m_nofChannels == 1) {
  304. if (buffer.m_bitsPerSample == 8)
  305. buffer.m_sampleFunction = sampleFunction8bitMono;
  306. if (buffer.m_bitsPerSample == 16)
  307. buffer.m_sampleFunction = sampleFunction16bitMono;
  308. if (buffer.m_bitsPerSample == 32)
  309. buffer.m_sampleFunction = sampleFunction32bitMono;
  310. } else {
  311. if (buffer.m_bitsPerSample == 8)
  312. buffer.m_sampleFunction = sampleFunction8bitStereo;
  313. if (buffer.m_bitsPerSample == 16)
  314. buffer.m_sampleFunction = sampleFunction16bitStereo;
  315. if (buffer.m_bitsPerSample == 32)
  316. buffer.m_sampleFunction = sampleFunction32bitStereo;
  317. }
  318. if (!buffer.m_sampleFunction) {
  319. // Unknown bit rate!
  320. DEBUG_INFO("Unknown bit rate:" << buffer.m_bitsPerSample);
  321. return false;
  322. }
  323. return true;
  324. }