Exemple #1
0
Boolean CASpeexDecoder::GenerateFrames()
{
    Boolean ret = true;
    int result;

    mBDCStatus = kBDCStatusOK;
    SpeexFramePacket &sfp = mSpeexFPList.front();

    speex_bits_read_from(&mSpeexBits, reinterpret_cast<char*> (mBDCBuffer.GetData()), sfp.bytes);

    if (sfp.frames > 0 && (sfp.frames - mSpeexHeader.frame_size * mSpeexHeader.frames_per_packet > 0)) {
        UInt32 zeroBytes = mOutputFormat.FramesToBytes(sfp.frames - mSpeexHeader.frame_size * mSpeexHeader.frames_per_packet);
        memset(mOutBuffer + mOutBufferUsedSize, 0, zeroBytes);
        mOutBufferUsedSize += zeroBytes;
    }

    for (SInt32 i = 0; i < mSpeexHeader.frames_per_packet; i++) {
        if (mOutputFormat.mFormatFlags & kAudioFormatFlagsNativeFloatPacked != 0)
            result = speex_decode(mSpeexDecoderState, &mSpeexBits, reinterpret_cast<float*> (mOutBuffer + mOutBufferUsedSize));
        else
            result = speex_decode_int(mSpeexDecoderState, &mSpeexBits, reinterpret_cast<spx_int16_t*> (mOutBuffer + mOutBufferUsedSize));

        if (result < 0) {
            mBDCStatus = kBDCStatusAbort;
            return false;
        }

        if (mSpeexHeader.nb_channels == 2) {
            if (mOutputFormat.mFormatFlags & kAudioFormatFlagsNativeFloatPacked != 0)
                speex_decode_stereo(reinterpret_cast<float*> (mOutBuffer + mOutBufferUsedSize), mSpeexHeader.frame_size, &mSpeexStereoState);
            else
                speex_decode_stereo_int(reinterpret_cast<spx_int16_t*> (mOutBuffer + mOutBufferUsedSize), mSpeexHeader.frame_size, &mSpeexStereoState);
        }
        mOutBufferUsedSize += mOutputFormat.FramesToBytes(mSpeexHeader.frame_size);
    }

    if (sfp.frames == 0) {
        mNumFrames += mSpeexHeader.frame_size * mSpeexHeader.frames_per_packet;
    } else if (sfp.frames > 0) {
        mNumFrames += sfp.frames;
        if (mSpeexHeader.frame_size * mSpeexHeader.frames_per_packet - sfp.frames != 0)
            mOutBufferStart += mOutputFormat.FramesToBytes(mSpeexHeader.frame_size * mSpeexHeader.frames_per_packet - sfp.frames);
    } else {
        mNumFrames -= sfp.frames;
    }

    mBDCBuffer.Zap(sfp.bytes);
    mSpeexFPList.erase(mSpeexFPList.begin());

    return ret;
}
Exemple #2
0
void speex_decode_stereo_int(short *data, int frame_size, SpeexStereoState *stereo)
{
   int i;
   /* FIXME: Do some dynamic allocation here */
   float float_data[2*MAX_IN_SAMPLES];
   speex_decode_stereo(float_data, frame_size, stereo);
   for (i=0;i<frame_size;i++)
   {
      if (float_data[i]>32767.f)
         data[i] = 32767;
      else if (float_data[i]<-32768.f)
         data[i] = -32768;
      else
         data[i] = (short)floor(.5+float_data[i]);
   }
}
UInt32 OggSpeexDecoder::ReadAudio(AudioBufferList *bufferList, UInt32 frameCount)
{
	if(!IsOpen() || NULL == bufferList || bufferList->mNumberBuffers != mFormat.mChannelsPerFrame || 0 == frameCount)
		return 0;

	UInt32 framesRead = 0;
	
	// Reset output buffer data size
	for(UInt32 i = 0; i < bufferList->mNumberBuffers; ++i)
		bufferList->mBuffers[i].mDataByteSize = 0;

	for(;;) {
		
		UInt32	framesRemaining	= frameCount - framesRead;
		UInt32	framesToSkip	= static_cast<UInt32>(bufferList->mBuffers[0].mDataByteSize / sizeof(float));
		UInt32	framesInBuffer	= static_cast<UInt32>(mBufferList->mBuffers[0].mDataByteSize / sizeof(float));
		UInt32	framesToCopy	= std::min(framesInBuffer, framesRemaining);
		
		// Copy data from the buffer to output
		for(UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i) {
			float *floatBuffer = static_cast<float *>(bufferList->mBuffers[i].mData);
			memcpy(floatBuffer + framesToSkip, mBufferList->mBuffers[i].mData, framesToCopy * sizeof(float));
			bufferList->mBuffers[i].mDataByteSize += static_cast<UInt32>(framesToCopy * sizeof(float));
			
			// Move remaining data in buffer to beginning
			if(framesToCopy != framesInBuffer) {
				floatBuffer = static_cast<float *>(mBufferList->mBuffers[i].mData);
				memmove(floatBuffer, floatBuffer + framesToCopy, (framesInBuffer - framesToCopy) * sizeof(float));
			}
			
			mBufferList->mBuffers[i].mDataByteSize -= static_cast<UInt32>(framesToCopy * sizeof(float));
		}
		
		framesRead += framesToCopy;
		
		// All requested frames were read
		if(framesRead == frameCount)
			break;
		
		// EOS reached
		if(mSpeexEOSReached)
			break;

		// Attempt to process the desired number of packets
		unsigned packetsDesired = 1;
		while(0 < packetsDesired && !mSpeexEOSReached) {

			// Process any packets in the current page
			while(0 < packetsDesired && !mSpeexEOSReached) {

				// Grab a packet from the streaming layer
				ogg_packet oggPacket;
				int result = ogg_stream_packetout(&mOggStreamState, &oggPacket);
				if(-1 == result) {
					LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Ogg Speex decoding error: Ogg loss of streaming");
					break;
				}
				
				// If result is 0, there is insufficient data to assemble a packet
				if(0 == result)
					break;

				// Otherwise, we got a valid packet for processing
				if(1 == result) {
					if(5 <= oggPacket.bytes && !memcmp(oggPacket.packet, "Speex", 5))
						mSpeexSerialNumber = mOggStreamState.serialno;
					
					if(-1 == mSpeexSerialNumber || mOggStreamState.serialno != mSpeexSerialNumber)
						break;
					
					// Ignore the following:
					//  - Speex comments in packet #2
					//  - Extra headers (optionally) in packets 3+
					if(1 != mOggPacketCount && 1 + mExtraSpeexHeaderCount <= mOggPacketCount) {
						// Detect Speex EOS
						if(oggPacket.e_o_s && mOggStreamState.serialno == mSpeexSerialNumber)
							mSpeexEOSReached = true;

						// SPEEX_GET_FRAME_SIZE is in samples
						spx_int32_t speexFrameSize;
						speex_decoder_ctl(mSpeexDecoder, SPEEX_GET_FRAME_SIZE, &speexFrameSize);
						float buffer [(2 == mFormat.mChannelsPerFrame) ? 2 * speexFrameSize : speexFrameSize];
						
						// Copy the Ogg packet to the Speex bitstream
						speex_bits_read_from(&mSpeexBits, (char *)oggPacket.packet, static_cast<int>(oggPacket.bytes));
						
						// Decode each frame in the Speex packet
						for(spx_int32_t i = 0; i < mSpeexFramesPerOggPacket; ++i) {
							
							result = speex_decode(mSpeexDecoder, &mSpeexBits, buffer);

							// -1 indicates EOS
							if(-1 == result)
								break;
							else if(-2 == result) {
								LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Ogg Speex decoding error: possible corrupted stream");
								break;
							}
							
							if(0 > speex_bits_remaining(&mSpeexBits)) {
								LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Ogg Speex decoding overflow: possible corrupted stream");
								break;
							}
							
							// Normalize the values
							float maxSampleValue = 1u << 15;
							vDSP_vsdiv(buffer, 1, &maxSampleValue, buffer, 1, speexFrameSize);

							// Copy the frames from the decoding buffer to the output buffer, skipping over any frames already decoded
							framesInBuffer = static_cast<UInt32>(mBufferList->mBuffers[0].mDataByteSize / sizeof(float));
							memcpy(static_cast<float *>(mBufferList->mBuffers[0].mData) + framesInBuffer, buffer, speexFrameSize * sizeof(float));
							mBufferList->mBuffers[0].mDataByteSize += static_cast<UInt32>(speexFrameSize * sizeof(float));
							
							// Process stereo channel, if present
							if(2 == mFormat.mChannelsPerFrame) {
								speex_decode_stereo(buffer, speexFrameSize, mSpeexStereoState);
								vDSP_vsdiv(buffer + speexFrameSize, 1, &maxSampleValue, buffer + speexFrameSize, 1, speexFrameSize);

								memcpy(static_cast<float *>(mBufferList->mBuffers[1].mData) + framesInBuffer, buffer + speexFrameSize, speexFrameSize * sizeof(float));
								mBufferList->mBuffers[1].mDataByteSize += static_cast<UInt32>(speexFrameSize * sizeof(float));
							}
							
							// Packet processing finished
							--packetsDesired;
						}
					}

					++mOggPacketCount;
				}
			}
			
			// Grab a new Ogg page for processing, if necessary
			if(!mSpeexEOSReached && 0 < packetsDesired) {
				while(1 != ogg_sync_pageout(&mOggSyncState, &mOggPage)) {
					// Get the ogg buffer for writing
					char *data = ogg_sync_buffer(&mOggSyncState, READ_SIZE_BYTES);
					
					// Read bitstream from input file
					ssize_t bytesRead = GetInputSource()->Read(data, READ_SIZE_BYTES);
					if(-1 == bytesRead) {
						LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Unable to read from the input file");
						break;
					}
					
					ogg_sync_wrote(&mOggSyncState, bytesRead);

					// No more data available from input file
					if(0 == bytesRead)
						break;
				}
				
				// Ensure all Ogg streams are read
				if(ogg_page_serialno(&mOggPage) != mOggStreamState.serialno)
					ogg_stream_reset_serialno(&mOggStreamState, ogg_page_serialno(&mOggPage));

				// Get the resultant Ogg page
				int result = ogg_stream_pagein(&mOggStreamState, &mOggPage);
				if(0 != result) {
					LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Error reading Ogg page");
					break;
				}
			}
		}
	}
	
	mCurrentFrame += framesRead;

	if(0 == framesRead && mSpeexEOSReached)
		mTotalFrames = mCurrentFrame;

	return framesRead;
}
Exemple #4
0
static gint
xmms_speex_read (xmms_xform_t *xform, gpointer buf, gint len,
                 xmms_error_t *err)
{
	gint ret = 0, n;
	gfloat outfloat [2000];
	gint16 *outbuf = (gint16 *) buf;
	xmms_speex_data_t *data;
	xmms_error_t error;
	SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT;

	g_return_val_if_fail (xform, -1);

	data = xmms_xform_private_data_get (xform);
	g_return_val_if_fail (data, -1);

	/* convert from bytes to samples */
	len /= 2;

	/* first, copy already decoded samples over if we have any. */
	if (data->samples_count) {
		n = MIN (data->samples_count, len);

		memcpy (outbuf, data->samples_start, n * 2);
		data->samples_count -= n;

		if (!data->samples_count) {
			data->samples_start = data->samples_buf;
		} else {
			data->samples_start += n;
		}

		/* convert from samples to bytes */
		return n * 2;
	}

	while (42) {
		gint samples_per_frame;

		samples_per_frame = data->speexheader->frame_size *
		                    data->speexheader->nb_channels;

		while (ogg_stream_packetout (&data->stream_state, &data->ogg_packet) == 1) {
			gint frame;

			speex_bits_read_from (&data->speex_bits,
			                      (char *)data->ogg_packet.packet,
			                      data->ogg_packet.bytes);

			for (frame = 0; frame < data->speexheader->frames_per_packet; frame++) {
				gint cnt;

				speex_decode (data->speex_state, &data->speex_bits, outfloat);

				if (data->speexheader->nb_channels == 2) {
					speex_decode_stereo (outfloat, data->speexheader->frame_size,&stereo);
				}

				n = MIN (samples_per_frame, len);

				/* copy as many samples to the output buffer as
				 * possible.
				 */
				for (cnt = 0; cnt < n; cnt++) {
					*outbuf++ = outfloat[cnt];
					len--;
					ret += 2;
				}

				/* store the remaining samples for later use */
				for (; cnt < samples_per_frame; cnt++) {
					data->samples_buf[data->samples_count++] =
						outfloat[cnt];
				}
			}

			return ret;
		}

		/* Need more data */

		do {
			gint ret;

			data->ogg_data = ogg_sync_buffer (&data->sync_state, 200);
			ret = xmms_xform_read (xform, data->ogg_data, 200, &error);
			ogg_sync_wrote (&data->sync_state, ret);

			if (ret <= 0) {
				return ret;
			}
		} while (ogg_sync_pageout (&data->sync_state, &data->ogg_page) != 1);

		ogg_stream_pagein (&data->stream_state, &data->ogg_page);
	}
}