示例#1
0
文件: aac.cpp 项目: Hellzed/xoreos
AudioStream *AACDecoder::decodeFrame(Common::SeekableReadStream &stream) {
	// read everything into a buffer
	uint32 inBufferPos = 0;
	uint32 inBufferSize = stream.size();
	byte *inBuffer = new byte[inBufferSize];
	stream.read(inBuffer, inBufferSize);

	QueuingAudioStream *audioStream = makeQueuingAudioStream(_rate, _channels);

	// Decode until we have enough samples (or there's no more left)
	while (inBufferPos < inBufferSize) {
		NeAACDecFrameInfo frameInfo;
		void *decodedSamples = NeAACDecDecode(_handle, &frameInfo, inBuffer + inBufferPos, inBufferSize - inBufferPos);

		if (frameInfo.error != 0)
			throw Common::Exception("Failed to decode AAC frame: %s", NeAACDecGetErrorMessage(frameInfo.error));

		byte *buffer = (byte *)malloc(frameInfo.samples * 2);
		memcpy(buffer, decodedSamples, frameInfo.samples * 2);

		byte flags = FLAG_16BITS;

#ifdef XOREOS_LITTLE_ENDIAN
		flags |= FLAG_LITTLE_ENDIAN;
#endif

		audioStream->queueAudioStream(makePCMStream(new Common::MemoryReadStream(buffer, frameInfo.samples * 2), _rate, flags, _channels, true), true);

		inBufferPos += frameInfo.bytesconsumed;
	}

	return audioStream;
}
示例#2
0
RewindableAudioStream *makeWAVStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse) {
	int size, rate;
	byte flags;
	uint16 type;
	int blockAlign;

	if (!loadWAVFromStream(*stream, size, rate, flags, &type, &blockAlign)) {
		if (disposeAfterUse == DisposeAfterUse::YES)
			delete stream;
		return 0;
	}

	if (type == 1) {
		// Raw PCM, make sure the last packet is complete
		uint sampleSize = (flags & Audio::FLAG_16BITS ? 2 : 1) * (flags & Audio::FLAG_STEREO ? 2 : 1);
		if (size % sampleSize != 0) {
			warning("makeWAVStream: Trying to play a WAVE file with an incomplete PCM packet");
			size &= ~(sampleSize - 1);
		}
	}

	Common::SeekableReadStream *substream = new Common::SeekableSubReadStream(stream, stream->pos(), stream->pos() + size, disposeAfterUse);

	switch (type) {
	case 1:
		// PCM
		return makePCMStream(substream, rate, flags);
	case 2:
		// MS ADPCM
		return makeADPCMStream(substream, DisposeAfterUse::YES, Audio::kADPCMMS, rate, (flags & Audio::FLAG_STEREO) ? 2 : 1, blockAlign);
	case 17:
		// MS IMA ADPCM
		return makeADPCMStream(substream, DisposeAfterUse::YES, Audio::kADPCMMSIma, rate, (flags & Audio::FLAG_STEREO) ? 2 : 1, blockAlign);
	default:
		// Unknown
		return 0;
	}
}
示例#3
0
RewindableAudioStream *makeWAVStream(Common::SeekableReadStream *stream, bool disposeAfterUse) {
	if (stream->readUint32BE() != MKTAG('R', 'I', 'F', 'F'))
		throw Common::Exception("makeWAVStream(): No 'RIFF' header");

	/* uint32 fileSize = */ stream->readUint32LE();

	if (stream->readUint32BE() != MKTAG('W', 'A', 'V', 'E'))
		throw Common::Exception("makeWAVStream(): No 'WAVE' RIFF type");

	if (stream->readUint32BE() != MKTAG('f', 'm', 't', ' '))
		throw Common::Exception("makeWAVStream(): No 'fmt ' chunk");

	uint32 fmtLength = stream->readUint32LE();
	if (fmtLength < 16) // A valid fmt chunk always contains at least 16 bytes
		throw Common::Exception("makeWAVStream(): Invalid wave format size %d", fmtLength);

	// Now parse the WAVEFORMAT(EX) structure
	uint16 compression = stream->readUint16LE();
	uint16 channels = stream->readUint16LE();
	uint32 sampleRate = stream->readUint32LE();
	/* uint32 avgBytesPerSecond = */ stream->readUint32LE();
	uint16 blockAlign = stream->readUint16LE();
	uint16 bitsPerSample = stream->readUint16LE();

	// Skip over the rest of the fmt chunk.
	stream->skip(fmtLength - 16);

	// Skip over all chunks until we hit the data
	for (;;) {
		if (stream->readUint32BE() == MKTAG('d', 'a', 't', 'a'))
			break;

		if (stream->eos())
			throw Common::Exception("makeWAVStream(): Unexpected eos");

		stream->skip(stream->readUint32LE());
	}

	uint32 size = stream->readUint32LE();
	Common::SeekableSubReadStream *subStream = new Common::SeekableSubReadStream(stream, stream->pos(), stream->pos() + size, disposeAfterUse);

	// Return the decoder we need
	switch (compression) {
	case kWavePCM: {
		byte flags = 0;

		// 8 bit data is unsigned, 16 bit data signed
		if (bitsPerSample == 8)
			flags |= FLAG_UNSIGNED;
		else if (bitsPerSample == 16)
			flags |= (FLAG_16BITS | FLAG_LITTLE_ENDIAN);
		else
			throw Common::Exception("makeWAVStream(): Unsupported PCM bits per sample %d", bitsPerSample);

		return makePCMStream(subStream, sampleRate, flags, channels, true);
	}
	case kWaveMSIMAADPCM:
	case kWaveMSIMAADPCM2:
		return makeADPCMStream(subStream, true, size, kADPCMMSIma, sampleRate, channels, blockAlign);
	case kWaveMSADPCM:
		return makeADPCMStream(subStream, true, size, kADPCMMS, sampleRate, channels, blockAlign);
	}

	throw Common::Exception("makeWAVStream(): Unhandled wave type 0x%04x", compression);
	return 0;
}
示例#4
0
void QueuingAudioStream::queueBuffer(byte *data, uint32 size, DisposeAfterUse::Flag disposeAfterUse, byte flags) {
	AudioStream *stream = makePCMStream(data, size, getRate(), flags, disposeAfterUse);
	queueAudioStream(stream, DisposeAfterUse::YES);
}