123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- /*
- * 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 <ostream>
- OPENMPT_NAMESPACE_BEGIN
- StreamWriterBase::StreamWriterBase(std::ostream &stream)
- : f(stream)
- , fStart(f.tellp())
- {
- return;
- }
- StreamWriterBase::~StreamWriterBase()
- {
- return;
- }
- template <mpt::endian endian, typename Tsample>
- static inline std::pair<bool, std::size_t> 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<Tsample>::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<const std::byte*>(interleaved), frameCount * channels * format.GetSampleFormat().GetSampleSize()))
- {
- success = false;
- }
- written += frameCount * channels * format.GetSampleFormat().GetSampleSize();
- } else
- {
- std::array<std::byte, mpt::IO::BUFFERSIZE_TINY> fbuf;
- mpt::IO::WriteBuffer<std::ostream> bf{f, fbuf};
- if(format.encoding == Encoder::Format::Encoding::Alaw)
- {
- if constexpr(std::is_same<Tsample, int16>::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<Tsample, int16>::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<Tsample>::value)
- {
- std::vector<typename mpt::make_float_endian<endian, Tsample>::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<endian, Tsample>::type(interleaved[channel]);
- }
- mpt::IO::WriteRaw(bf, reinterpret_cast<const std::byte*>(frameData.data()), channels * format.GetSampleFormat().GetSampleSize());
- written += channels * format.GetSampleFormat().GetSampleSize();
- interleaved += channels;
- }
- } else if constexpr(std::is_same<Tsample, int24>::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<std::byte, 3> 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<typename mpt::make_endian<endian, Tsample>::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<const std::byte*>(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<bool, std::size_t> 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<mpt::endian::little>(f, channels, format, frameCount, interleaved);
- }
- std::pair<bool, std::size_t> 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<mpt::endian::little>(f, channels, format, frameCount, interleaved);
- }
- std::pair<bool, std::size_t> 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<mpt::endian::little>(f, channels, format, frameCount, interleaved);
- }
- std::pair<bool, std::size_t> 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<mpt::endian::little>(f, channels, format, frameCount, interleaved);
- }
- std::pair<bool, std::size_t> 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<mpt::endian::little>(f, channels, format, frameCount, interleaved);
- }
- std::pair<bool, std::size_t> 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<mpt::endian::little>(f, channels, format, frameCount, interleaved);
- }
- std::pair<bool, std::size_t> 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<mpt::endian::little>(f, channels, format, frameCount, interleaved);
- }
- std::pair<bool, std::size_t> 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<mpt::endian::big>(f, channels, format, frameCount, interleaved);
- }
- std::pair<bool, std::size_t> 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<mpt::endian::big>(f, channels, format, frameCount, interleaved);
- }
- std::pair<bool, std::size_t> 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<mpt::endian::big>(f, channels, format, frameCount, interleaved);
- }
- std::pair<bool, std::size_t> 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<mpt::endian::big>(f, channels, format, frameCount, interleaved);
- }
- std::pair<bool, std::size_t> 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<mpt::endian::big>(f, channels, format, frameCount, interleaved);
- }
- std::pair<bool, std::size_t> 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<mpt::endian::big>(f, channels, format, frameCount, interleaved);
- }
- std::pair<bool, std::size_t> 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<mpt::endian::big>(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<uint64> &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<int>(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
|