/* * StreamEncoder.cpp * ----------------- * Purpose: Exporting streamed music files. * Notes : none * Authors: Joern Heusipp * OpenMPT Devs * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. */ #include "stdafx.h" #include "StreamEncoder.h" #include "mpt/io/base.hpp" #include "mpt/io/io.hpp" #include "mpt/io/io_stdstream.hpp" #include "mpt/io_write/buffer.hpp" #include "openmpt/soundbase/SampleEncode.hpp" #include "openmpt/soundbase/SampleFormat.hpp" #include OPENMPT_NAMESPACE_BEGIN StreamWriterBase::StreamWriterBase(std::ostream &stream) : f(stream) , fStart(f.tellp()) { return; } StreamWriterBase::~StreamWriterBase() { return; } template static inline std::pair WriteInterleavedImpl(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const Tsample *interleaved) { MPT_ASSERT(endian == format.endian); MPT_ASSERT(format.GetSampleFormat() == SampleFormatTraits::sampleFormat()); bool success = true; std::size_t written = 0; MPT_MAYBE_CONSTANT_IF(endian == mpt::get_endian() && format.encoding != Encoder::Format::Encoding::Alaw && format.encoding != Encoder::Format::Encoding::ulaw) { if(!mpt::IO::WriteRaw(f, reinterpret_cast(interleaved), frameCount * channels * format.GetSampleFormat().GetSampleSize())) { success = false; } written += frameCount * channels * format.GetSampleFormat().GetSampleSize(); } else { std::array fbuf; mpt::IO::WriteBuffer bf{f, fbuf}; if(format.encoding == Encoder::Format::Encoding::Alaw) { if constexpr(std::is_same::value) { SC::EncodeALaw conv; for(std::size_t frame = 0; frame < frameCount; ++frame) { for(uint16 channel = 0; channel < channels; ++channel) { std::byte sampledata = conv(interleaved[channel]); mpt::IO::WriteRaw(bf, &sampledata, 1); written += 1; } interleaved += channels; } } } else if(format.encoding == Encoder::Format::Encoding::ulaw) { if constexpr(std::is_same::value) { SC::EncodeuLaw conv; for(std::size_t frame = 0; frame < frameCount; ++frame) { for(uint16 channel = 0; channel < channels; ++channel) { std::byte sampledata = conv(interleaved[channel]); mpt::IO::WriteRaw(bf, &sampledata, 1); written += 1; } interleaved += channels; } } } else { if constexpr(std::is_floating_point::value) { std::vector::type> frameData(channels); for(std::size_t frame = 0; frame < frameCount; ++frame) { for(uint16 channel = 0; channel < channels; ++channel) { frameData[channel] = typename mpt::make_float_endian::type(interleaved[channel]); } mpt::IO::WriteRaw(bf, reinterpret_cast(frameData.data()), channels * format.GetSampleFormat().GetSampleSize()); written += channels * format.GetSampleFormat().GetSampleSize(); interleaved += channels; } } else if constexpr(std::is_same::value) { MPT_ASSERT(!mpt::endian_is_weird()); for(std::size_t frame = 0; frame < frameCount; ++frame) { for(uint16 channel = 0; channel < channels; ++channel) { std::array data; std::memcpy(data.data(), interleaved, 3); MPT_MAYBE_CONSTANT_IF(endian != mpt::get_endian()) { std::reverse(data.begin(), data.end()); } mpt::IO::Write(bf, data); written += data.size(); interleaved += 3; } } } else { std::vector::type> frameData(channels); for(std::size_t frame = 0; frame < frameCount; ++frame) { for(uint16 channel = 0; channel < channels; ++channel) { frameData[channel] = interleaved[channel]; } mpt::IO::WriteRaw(bf, reinterpret_cast(frameData.data()), channels * format.GetSampleFormat().GetSampleSize()); written += channels * format.GetSampleFormat().GetSampleSize(); interleaved += channels; } } } if(bf.HasWriteError()) { success = false; } } return std::make_pair(success, written); } std::pair WriteInterleavedLE(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const double *interleaved) { MPT_ASSERT(format.endian == mpt::endian::little); return WriteInterleavedImpl(f, channels, format, frameCount, interleaved); } std::pair WriteInterleavedLE(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const float *interleaved) { MPT_ASSERT(format.endian == mpt::endian::little); return WriteInterleavedImpl(f, channels, format, frameCount, interleaved); } std::pair WriteInterleavedLE(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const int32 *interleaved) { MPT_ASSERT(format.endian == mpt::endian::little); return WriteInterleavedImpl(f, channels, format, frameCount, interleaved); } std::pair WriteInterleavedLE(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const int24 *interleaved) { MPT_ASSERT(format.endian == mpt::endian::little); return WriteInterleavedImpl(f, channels, format, frameCount, interleaved); } std::pair WriteInterleavedLE(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const int16 *interleaved) { MPT_ASSERT(format.endian == mpt::endian::little); return WriteInterleavedImpl(f, channels, format, frameCount, interleaved); } std::pair WriteInterleavedLE(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const int8 *interleaved) { MPT_ASSERT(format.endian == mpt::endian::little); return WriteInterleavedImpl(f, channels, format, frameCount, interleaved); } std::pair WriteInterleavedLE(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const uint8 *interleaved) { MPT_ASSERT(format.endian == mpt::endian::little); return WriteInterleavedImpl(f, channels, format, frameCount, interleaved); } std::pair WriteInterleavedBE(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const double *interleaved) { MPT_ASSERT(format.endian == mpt::endian::big); return WriteInterleavedImpl(f, channels, format, frameCount, interleaved); } std::pair WriteInterleavedBE(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const float *interleaved) { MPT_ASSERT(format.endian == mpt::endian::big); return WriteInterleavedImpl(f, channels, format, frameCount, interleaved); } std::pair WriteInterleavedBE(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const int32 *interleaved) { MPT_ASSERT(format.endian == mpt::endian::big); return WriteInterleavedImpl(f, channels, format, frameCount, interleaved); } std::pair WriteInterleavedBE(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const int24 *interleaved) { MPT_ASSERT(format.endian == mpt::endian::big); return WriteInterleavedImpl(f, channels, format, frameCount, interleaved); } std::pair WriteInterleavedBE(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const int16 *interleaved) { MPT_ASSERT(format.endian == mpt::endian::big); return WriteInterleavedImpl(f, channels, format, frameCount, interleaved); } std::pair WriteInterleavedBE(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const int8 *interleaved) { MPT_ASSERT(format.endian == mpt::endian::big); return WriteInterleavedImpl(f, channels, format, frameCount, interleaved); } std::pair WriteInterleavedBE(std::ostream &f, uint16 channels, Encoder::Format format, std::size_t frameCount, const uint8 *interleaved) { MPT_ASSERT(format.endian == mpt::endian::big); return WriteInterleavedImpl(f, channels, format, frameCount, interleaved); } SampleFormat StreamWriterBase::GetSampleFormat() const { return SampleFormat::Float32; } void StreamWriterBase::WriteInterleaved(std::size_t frameCount, const double *interleaved) { MPT_UNREFERENCED_PARAMETER(frameCount); MPT_UNREFERENCED_PARAMETER(interleaved); MPT_ASSERT_NOTREACHED(); } void StreamWriterBase::WriteInterleaved(std::size_t frameCount, const float *interleaved) { MPT_UNREFERENCED_PARAMETER(frameCount); MPT_UNREFERENCED_PARAMETER(interleaved); MPT_ASSERT_NOTREACHED(); } void StreamWriterBase::WriteInterleaved(std::size_t frameCount, const int32 *interleaved) { MPT_UNREFERENCED_PARAMETER(frameCount); MPT_UNREFERENCED_PARAMETER(interleaved); MPT_ASSERT_NOTREACHED(); } void StreamWriterBase::WriteInterleaved(std::size_t frameCount, const int24 *interleaved) { MPT_UNREFERENCED_PARAMETER(frameCount); MPT_UNREFERENCED_PARAMETER(interleaved); MPT_ASSERT_NOTREACHED(); } void StreamWriterBase::WriteInterleaved(std::size_t frameCount, const int16 *interleaved) { MPT_UNREFERENCED_PARAMETER(frameCount); MPT_UNREFERENCED_PARAMETER(interleaved); MPT_ASSERT_NOTREACHED(); } void StreamWriterBase::WriteInterleaved(std::size_t frameCount, const int8 *interleaved) { MPT_UNREFERENCED_PARAMETER(frameCount); MPT_UNREFERENCED_PARAMETER(interleaved); MPT_ASSERT_NOTREACHED(); } void StreamWriterBase::WriteInterleaved(std::size_t frameCount, const uint8 *interleaved) { MPT_UNREFERENCED_PARAMETER(frameCount); MPT_UNREFERENCED_PARAMETER(interleaved); MPT_ASSERT_NOTREACHED(); } void StreamWriterBase::WriteCues(const std::vector &cues) { MPT_UNREFERENCED_PARAMETER(cues); } void StreamWriterBase::WriteFinalize() { return; } void StreamWriterBase::WriteBuffer() { if(!f) { return; } if(buf.empty()) { return; } f.write(buf.data(), buf.size()); buf.resize(0); } void EncoderFactoryBase::SetTraits(const Encoder::Traits &traits) { m_Traits = traits; } bool EncoderFactoryBase::IsBitrateSupported(int samplerate, int channels, int bitrate) const { MPT_UNREFERENCED_PARAMETER(samplerate); MPT_UNREFERENCED_PARAMETER(channels); MPT_UNREFERENCED_PARAMETER(bitrate); return true; } mpt::ustring EncoderFactoryBase::DescribeQuality(float quality) const { return MPT_UFORMAT("VBR {}%")(static_cast(quality * 100.0f)); } mpt::ustring EncoderFactoryBase::DescribeBitrateVBR(int bitrate) const { return MPT_UFORMAT("VBR {} kbit")(bitrate); } mpt::ustring EncoderFactoryBase::DescribeBitrateABR(int bitrate) const { return MPT_UFORMAT("ABR {} kbit")(bitrate); } mpt::ustring EncoderFactoryBase::DescribeBitrateCBR(int bitrate) const { return MPT_UFORMAT("CBR {} kbit")(bitrate); } OPENMPT_NAMESPACE_END