uint32 nuiAiffReader::ReadIN(void* pBuffer, uint32 SampleFrames, nuiSampleBitFormat format) { if (!SampleFrames) return 0; SetPosition((uint32)mPosition); const uint32 channels = mInfo.GetChannels(); uint32 length = mInfo.GetSampleFrames(); if (mPosition >= length) return 0; SampleFrames = MIN(SampleFrames, length - mPosition); const uint64 SamplePointsToRead = SampleFrames * channels; uint32 SampleFramesRead = 0; switch(format) { case eSampleInt16 : { switch (mInfo.GetBitsPerSample()) { case 8 : { int16* pTempInt16 = (int16*)pBuffer; uint32 sizeRead = mrStream.ReadUInt8( ((uint8*)pTempInt16) + SamplePointsToRead , SamplePointsToRead); SampleFramesRead = sizeRead / channels; nuiAudioConvert_Signed8bitsBufferTo16Bits(pTempInt16, sizeRead); } break; case 16 : { uint32 sizeRead = mrStream.ReadInt16( (int16*)pBuffer, SamplePointsToRead); SampleFramesRead = sizeRead / channels; } break; case 24 : case 32 : default: SampleFramesRead = 0; break; } } break; case eSampleFloat32 : { switch ( mInfo.GetBitsPerSample() ) { case 8 : { float* pTempFloat = (float*)pBuffer; uint32 sizeRead = mrStream.ReadUInt8( (uint8*)pTempFloat + 3 * SamplePointsToRead , SamplePointsToRead); SampleFramesRead = sizeRead / channels; nuiAudioConvert_Signed8bitsBufferToFloat(pTempFloat, sizeRead); } break; case 16 : { float* pTempFloat = (float*)pBuffer; uint32 sizeRead = mrStream.ReadInt16( (int16*)pTempFloat + SamplePointsToRead, SamplePointsToRead); SampleFramesRead = sizeRead / channels; nuiAudioConvert_16bitsBufferToFloat(pTempFloat, SamplePointsToRead); } break; case 24 : { float* pTempFloat = (float*)pBuffer; uint8* pTempBuffer; pTempBuffer = new uint8[SamplePointsToRead * 3]; //nb of sample points * 3 bytes (24 bits) = nb of bytes to read uint32 sizeRead = mrStream.ReadUInt8(pTempBuffer, SamplePointsToRead * 3); SampleFramesRead = sizeRead / channels / 3; for (uint32 i = 0; i < sizeRead / 3; i++) { pTempFloat[i] = nuiAudioConvert_24bitsToFloatFromBigEndian(pTempBuffer + (3 * i)); } delete[] pTempBuffer; } break; case 32 : { uint32 sizeRead = mrStream.ReadFloat((float*)pBuffer, SamplePointsToRead); SampleFramesRead = sizeRead / channels; mPosition += SampleFramesRead; } break; default: SampleFramesRead = 0; break; } } break; default : SampleFramesRead = 0; break; } mPosition += SampleFramesRead; return SampleFramesRead; }
int32 nuiAudioDecoder::ReadIN(void* pBuffer, int32 sampleframes, nuiSampleBitFormat format) { if (!mInitialized) return 0; SetPosition(mPosition); int32 BitsPerSample = mInfo.GetBitsPerSample(); int32 channels = mInfo.GetChannels(); int32 frameSize = channels * (mInfo.GetBitsPerSample() / 8.f); int32 outBytes = sampleframes * frameSize; unsigned char* pTemp; bool allocated = false; if (BitsPerSample != 16 && BitsPerSample != 32) { NGL_ASSERT(0); return 0; } else if ( ((format == eSampleFloat32) && (BitsPerSample == 32)) || ((format == eSampleInt16) && (BitsPerSample == 16)) ) { pTemp = (unsigned char*)pBuffer; } else { pTemp = new unsigned char[outBytes]; allocated = true; } unsigned char* pIn = NULL; int32 bytesDone = 0; int err = MPG123_OK; int32 bytesRead = -1; while (outBytes && err != MPG123_DONE && bytesRead != 0) { size_t outBytesDone = 0; unsigned char* pOut = pTemp + bytesDone; err = mpg123_decode(mpPrivate->mpHandle, NULL, 0, pOut, outBytes, &outBytesDone); outBytes -= outBytesDone; bytesDone += outBytesDone; if (err == MPG123_NEW_FORMAT) { long r; int c; int e; mpg123_getformat(mpPrivate->mpHandle, &r, &c, &e); } // feed decoder if needed bytesRead = -1; while (err == MPG123_NEED_MORE && bytesRead != 0) { int32 inBytes = DECODER_INPUT_SIZE; if (!pIn) { pIn = new unsigned char[inBytes]; } bytesRead = mrStream.ReadUInt8(pIn, inBytes); err = mpg123_decode(mpPrivate->mpHandle, pIn, bytesRead, NULL, 0, &outBytesDone); } if (err != MPG123_OK && err != MPG123_DONE) { NGL_LOG("nuiAudioDecoder", NGL_LOG_INFO, "mpg123 error while decoding: %s", mpg123_strerror(mpPrivate->mpHandle)); } } int32 frames = bytesDone / frameSize; if (format == eSampleFloat32 && BitsPerSample == 16) { // convert '16 bits int' samples in pTemp to '32 bits float' samples in pBuffer int16* pSrc = (int16*)pTemp; float* pCopy = (float*)( ((int16*)pBuffer) + frames * channels ); float* pFloat = (float*)pBuffer; // copy int16 data to the second half of the output buffer // => nuiAudioConvert_16bitsBufferToFloat converts in place // 'int16' samples atored in the second half of the buffer are converted in 'float' samples filling all the buffer (sizeof(float) == 2 * sizeof(int16)) memcpy(pCopy, pSrc, frames * channels * sizeof(int16)); nuiAudioConvert_16bitsBufferToFloat(pFloat, frames * channels); // convert in place (int16 to float) } else if (format == eSampleInt16 && BitsPerSample == 32) { // convert '32 bits float' samples in pTemp to '16 bits int' samples in pBuffer float* pFloat = (float*)pTemp; int16* pInt16 = (int16*)pBuffer; nuiAudioConvert_FloatBufferTo16bits(pFloat, pInt16, frames * channels); } if (allocated) { delete[] pTemp; } if (pIn) { delete[] pIn; } mPosition += frames; return frames; }