StreamEncoderWAV.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * StreamEncoder.cpp
  3. * -----------------
  4. * Purpose: Exporting streamed music files.
  5. * Notes : none
  6. * Authors: Joern Heusipp
  7. * OpenMPT Devs
  8. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  9. */
  10. #include "stdafx.h"
  11. #include "StreamEncoder.h"
  12. #include "StreamEncoderWAV.h"
  13. #include "mpt/io/io.hpp"
  14. #include "mpt/io/io_stdstream.hpp"
  15. #include "Mptrack.h"
  16. #include "TrackerSettings.h"
  17. #include "../soundlib/Sndfile.h"
  18. #include "../soundlib/WAVTools.h"
  19. OPENMPT_NAMESPACE_BEGIN
  20. class WavStreamWriter : public IAudioStreamEncoder
  21. {
  22. private:
  23. const WAVEncoder &enc;
  24. std::ostream &f;
  25. mpt::IO::OFile<std::ostream> ff;
  26. std::unique_ptr<WAVWriter> fileWAV;
  27. Encoder::Settings settings;
  28. public:
  29. WavStreamWriter(const WAVEncoder &enc_, std::ostream &file, const Encoder::Settings &settings_, const FileTags &tags)
  30. : enc(enc_)
  31. , f(file)
  32. , ff(f)
  33. , fileWAV(nullptr)
  34. , settings(settings_)
  35. {
  36. MPT_ASSERT(settings.Format.GetSampleFormat().IsValid());
  37. MPT_ASSERT(settings.Samplerate > 0);
  38. MPT_ASSERT(settings.Channels > 0);
  39. fileWAV = std::make_unique<WAVWriter>(ff);
  40. fileWAV->WriteFormat(settings.Samplerate, settings.Format.GetSampleFormat().GetBitsPerSample(), settings.Channels, settings.Format.GetSampleFormat().IsFloat() ? WAVFormatChunk::fmtFloat : WAVFormatChunk::fmtPCM);
  41. if(settings.Tags)
  42. {
  43. fileWAV->WriteMetatags(tags);
  44. }
  45. fileWAV->StartChunk(RIFFChunk::iddata);
  46. }
  47. SampleFormat GetSampleFormat() const override
  48. {
  49. return settings.Format.GetSampleFormat();
  50. }
  51. void WriteInterleaved(std::size_t frameCount, const double *interleaved) override
  52. {
  53. fileWAV->WriteBeforeDirect();
  54. auto result = WriteInterleavedLE(f, settings.Channels, settings.Format, frameCount, interleaved);
  55. fileWAV->WriteAfterDirect(result.first, result.second);
  56. }
  57. void WriteInterleaved(std::size_t frameCount, const float *interleaved) override
  58. {
  59. fileWAV->WriteBeforeDirect();
  60. auto result = WriteInterleavedLE(f, settings.Channels, settings.Format, frameCount, interleaved);
  61. fileWAV->WriteAfterDirect(result.first, result.second);
  62. }
  63. void WriteInterleaved(std::size_t frameCount, const int32 *interleaved) override
  64. {
  65. fileWAV->WriteBeforeDirect();
  66. auto result = WriteInterleavedLE(f, settings.Channels, settings.Format, frameCount, interleaved);
  67. fileWAV->WriteAfterDirect(result.first, result.second);
  68. }
  69. void WriteInterleaved(std::size_t frameCount, const int24 *interleaved) override
  70. {
  71. fileWAV->WriteBeforeDirect();
  72. auto result = WriteInterleavedLE(f, settings.Channels, settings.Format, frameCount, interleaved);
  73. fileWAV->WriteAfterDirect(result.first, result.second);
  74. }
  75. void WriteInterleaved(std::size_t frameCount, const int16 *interleaved) override
  76. {
  77. fileWAV->WriteBeforeDirect();
  78. auto result = WriteInterleavedLE(f, settings.Channels, settings.Format, frameCount, interleaved);
  79. fileWAV->WriteAfterDirect(result.first, result.second);
  80. }
  81. void WriteInterleaved(std::size_t frameCount, const int8 *interleaved) override
  82. {
  83. fileWAV->WriteBeforeDirect();
  84. auto result = WriteInterleavedLE(f, settings.Channels, settings.Format, frameCount, interleaved);
  85. fileWAV->WriteAfterDirect(result.first, result.second);
  86. }
  87. void WriteInterleaved(std::size_t frameCount, const uint8 *interleaved) override
  88. {
  89. fileWAV->WriteBeforeDirect();
  90. auto result = WriteInterleavedLE(f, settings.Channels, settings.Format, frameCount, interleaved);
  91. fileWAV->WriteAfterDirect(result.first, result.second);
  92. }
  93. void WriteCues(const std::vector<uint64> &cues) override
  94. {
  95. if(!cues.empty())
  96. {
  97. // Cue point header
  98. fileWAV->StartChunk(RIFFChunk::idcue_);
  99. uint32le numPoints;
  100. numPoints = mpt::saturate_cast<uint32>(cues.size());
  101. fileWAV->Write(numPoints);
  102. // Write all cue points
  103. uint32 index = 0;
  104. for(auto cue : cues)
  105. {
  106. WAVCuePoint cuePoint{};
  107. cuePoint.id = index++;
  108. cuePoint.position = static_cast<uint32>(cue);
  109. cuePoint.riffChunkID = static_cast<uint32>(RIFFChunk::iddata);
  110. cuePoint.chunkStart = 0; // we use no Wave List Chunk (wavl) as we have only one data block, so this should be 0.
  111. cuePoint.blockStart = 0; // ditto
  112. cuePoint.offset = cuePoint.position;
  113. fileWAV->Write(cuePoint);
  114. }
  115. }
  116. }
  117. void WriteFinalize() override
  118. {
  119. fileWAV->Finalize();
  120. }
  121. virtual ~WavStreamWriter()
  122. {
  123. fileWAV = nullptr;
  124. }
  125. };
  126. WAVEncoder::WAVEncoder()
  127. {
  128. Encoder::Traits traits;
  129. traits.fileExtension = P_("wav");
  130. traits.fileShortDescription = U_("Wave");
  131. traits.fileDescription = U_("Microsoft RIFF Wave");
  132. traits.encoderSettingsName = U_("Wave");
  133. traits.canTags = true;
  134. traits.canCues = true;
  135. traits.maxChannels = 4;
  136. traits.samplerates = TrackerSettings::Instance().GetSampleRates();
  137. traits.modes = Encoder::ModeLossless;
  138. traits.formats.push_back({ Encoder::Format::Encoding::Float, 64, mpt::endian::little });
  139. traits.formats.push_back({ Encoder::Format::Encoding::Float, 32, mpt::endian::little });
  140. traits.formats.push_back({ Encoder::Format::Encoding::Integer, 32, mpt::endian::little });
  141. traits.formats.push_back({ Encoder::Format::Encoding::Integer, 24, mpt::endian::little });
  142. traits.formats.push_back({ Encoder::Format::Encoding::Integer, 16, mpt::endian::little });
  143. traits.formats.push_back({ Encoder::Format::Encoding::Unsigned, 8, mpt::endian::little });
  144. traits.defaultSamplerate = 48000;
  145. traits.defaultChannels = 2;
  146. traits.defaultMode = Encoder::ModeLossless;
  147. traits.defaultFormat = { Encoder::Format::Encoding::Float, 32, mpt::endian::little };
  148. SetTraits(traits);
  149. }
  150. bool WAVEncoder::IsAvailable() const
  151. {
  152. return true;
  153. }
  154. std::unique_ptr<IAudioStreamEncoder> WAVEncoder::ConstructStreamEncoder(std::ostream &file, const Encoder::Settings &settings, const FileTags &tags) const
  155. {
  156. if(!IsAvailable())
  157. {
  158. return nullptr;
  159. }
  160. return std::make_unique<WavStreamWriter>(*this, file, settings, tags);
  161. }
  162. OPENMPT_NAMESPACE_END