123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- /*
- * StreamEncoderAU.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 "StreamEncoderAU.h"
- #include "mpt/io/io.hpp"
- #include "mpt/io/io_stdstream.hpp"
- #include "Mptrack.h"
- #include "TrackerSettings.h"
- #include "../common/mptFileIO.h"
- OPENMPT_NAMESPACE_BEGIN
- class AUStreamWriter : public IAudioStreamEncoder
- {
- private:
- const AUEncoder &enc;
- std::ostream &f;
- Encoder::Settings settings;
- private:
- static std::string TagToAnnotation(const std::string & field, const mpt::ustring & tag)
- {
- if(tag.empty())
- {
- return std::string();
- }
- return MPT_AFORMAT("{}={}\n")(field, mpt::ToCharset(mpt::Charset::UTF8, mpt::String::Replace(tag, U_("="), MPT_UTF8("\xEF\xBF\xBD")))); // U+FFFD
- }
- public:
- AUStreamWriter(const AUEncoder &enc_, std::ostream &file, const Encoder::Settings &settings_, const FileTags &tags)
- : enc(enc_)
- , f(file)
- , settings(settings_)
- {
- MPT_ASSERT(settings.Format.GetSampleFormat().IsValid());
- MPT_ASSERT(settings.Samplerate > 0);
- MPT_ASSERT(settings.Channels > 0);
- std::string annotation;
- std::size_t annotationSize = 0;
- std::size_t annotationTotalSize = 8;
- if(settings.Tags)
- {
- // same format as invented by sox and implemented by ffmpeg
- annotation += TagToAnnotation("title", tags.title);
- annotation += TagToAnnotation("artist", tags.artist);
- annotation += TagToAnnotation("album", tags.album);
- annotation += TagToAnnotation("track", tags.trackno);
- annotation += TagToAnnotation("genre", tags.genre);
- annotation += TagToAnnotation("comment", tags.comments);
- annotationSize = annotation.length() + 1;
- annotationTotalSize = annotationSize;
- if(settings.Details.AUPaddingAlignHint > 0)
- {
- annotationTotalSize = mpt::align_up<std::size_t>(24u + annotationTotalSize, settings.Details.AUPaddingAlignHint) - 24u;
- }
- annotationTotalSize = mpt::align_up<std::size_t>(annotationTotalSize, 8u);
- }
- MPT_ASSERT(annotationTotalSize >= annotationSize);
- MPT_ASSERT(annotationTotalSize % 8 == 0);
- mpt::IO::WriteText(f, ".snd");
- mpt::IO::WriteIntBE<uint32>(f, mpt::saturate_cast<uint32>(24u + annotationTotalSize));
- mpt::IO::WriteIntBE<uint32>(f, ~uint32(0));
- uint32 encoding = 0;
- if(settings.Format.encoding == Encoder::Format::Encoding::Float)
- {
- switch(settings.Format.bits)
- {
- case 32: encoding = 6; break;
- case 64: encoding = 7; break;
- }
- } else if(settings.Format.encoding == Encoder::Format::Encoding::Integer)
- {
- switch(settings.Format.bits)
- {
- case 8: encoding = 2; break;
- case 16: encoding = 3; break;
- case 24: encoding = 4; break;
- case 32: encoding = 5; break;
- }
- } else if(settings.Format.encoding == Encoder::Format::Encoding::Alaw)
- {
- encoding = 27;
- } else if (settings.Format.encoding == Encoder::Format::Encoding::ulaw)
- {
- encoding = 1;
- }
- mpt::IO::WriteIntBE<uint32>(f, encoding);
- mpt::IO::WriteIntBE<uint32>(f, settings.Samplerate);
- mpt::IO::WriteIntBE<uint32>(f, settings.Channels);
- if(annotationSize > 0)
- {
- mpt::IO::WriteText(f, annotation);
- mpt::IO::WriteIntBE<uint8>(f, '\0');
- }
- for(std::size_t i = 0; i < annotationTotalSize - annotationSize; ++i)
- {
- mpt::IO::WriteIntBE<uint8>(f, '\0');
- }
- }
- SampleFormat GetSampleFormat() const override
- {
- return settings.Format.GetSampleFormat();
- }
- void WriteInterleaved(std::size_t frameCount, const double *interleaved) override
- {
- WriteInterleavedBE(f, settings.Channels, settings.Format, frameCount, interleaved);
- }
- void WriteInterleaved(std::size_t frameCount, const float *interleaved) override
- {
- WriteInterleavedBE(f, settings.Channels, settings.Format, frameCount, interleaved);
- }
- void WriteInterleaved(std::size_t frameCount, const int32 *interleaved) override
- {
- WriteInterleavedBE(f, settings.Channels, settings.Format, frameCount, interleaved);
- }
- void WriteInterleaved(std::size_t frameCount, const int24 *interleaved) override
- {
- WriteInterleavedBE(f, settings.Channels, settings.Format, frameCount, interleaved);
- }
- void WriteInterleaved(std::size_t frameCount, const int16 *interleaved) override
- {
- WriteInterleavedBE(f, settings.Channels, settings.Format, frameCount, interleaved);
- }
- void WriteInterleaved(std::size_t frameCount, const int8 *interleaved) override
- {
- WriteInterleavedBE(f, settings.Channels, settings.Format, frameCount, interleaved);
- }
- void WriteInterleaved(std::size_t frameCount, const uint8 *interleaved) override
- {
- WriteInterleavedBE(f, settings.Channels, settings.Format, frameCount, interleaved);
- }
- void WriteCues(const std::vector<uint64> &cues) override
- {
- MPT_UNREFERENCED_PARAMETER(cues);
- }
- void WriteFinalize() override
- {
- return;
- }
- virtual ~AUStreamWriter()
- {
- return;
- }
- };
- AUEncoder::AUEncoder()
- {
- Encoder::Traits traits;
- traits.fileExtension = P_("au");
- traits.fileShortDescription = U_("AU");
- traits.fileDescription = U_("NeXT/Sun Audio");
- traits.encoderSettingsName = U_("AU");
- traits.canTags = true;
- traits.canCues = false;
- traits.maxChannels = 4;
- traits.samplerates = TrackerSettings::Instance().GetSampleRates();
- traits.modes = Encoder::ModeLossless;
- traits.formats.push_back({ Encoder::Format::Encoding::Float, 64, mpt::endian::big });
- traits.formats.push_back({ Encoder::Format::Encoding::Float, 32, mpt::endian::big });
- traits.formats.push_back({ Encoder::Format::Encoding::Integer, 32, mpt::endian::big });
- traits.formats.push_back({ Encoder::Format::Encoding::Integer, 24, mpt::endian::big });
- traits.formats.push_back({ Encoder::Format::Encoding::Integer, 16, mpt::endian::big });
- traits.formats.push_back({ Encoder::Format::Encoding::Integer, 8, mpt::endian::big });
- traits.formats.push_back({ Encoder::Format::Encoding::Alaw, 16, mpt::endian::big });
- traits.formats.push_back({ Encoder::Format::Encoding::ulaw, 16, mpt::endian::big });
- traits.defaultSamplerate = 48000;
- traits.defaultChannels = 2;
- traits.defaultMode = Encoder::ModeLossless;
- traits.defaultFormat = { Encoder::Format::Encoding::Float, 32, mpt::endian::big };
- SetTraits(traits);
- }
- bool AUEncoder::IsAvailable() const
- {
- return true;
- }
- std::unique_ptr<IAudioStreamEncoder> AUEncoder::ConstructStreamEncoder(std::ostream &file, const Encoder::Settings &settings, const FileTags &tags) const
- {
- if(!IsAvailable())
- {
- return nullptr;
- }
- return std::make_unique<AUStreamWriter>(*this, file, settings, tags);
- }
- OPENMPT_NAMESPACE_END
|