| 1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
| 2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
| 3 | #pragma once |
| 4 | |
| 5 | #include "BsCorePrerequisites.h" |
| 6 | #include "vorbis/vorbisenc.h" |
| 7 | |
| 8 | namespace bs |
| 9 | { |
| 10 | /** @addtogroup OpenAudio |
| 11 | * @{ |
| 12 | */ |
| 13 | |
| 14 | /** Used for encoding PCM to Ogg Vorbis audio data. */ |
| 15 | class OggVorbisEncoder |
| 16 | { |
| 17 | public: |
| 18 | OggVorbisEncoder() = default; |
| 19 | ~OggVorbisEncoder(); |
| 20 | |
| 21 | /** |
| 22 | * Sets up the writer. Should be called before calling write(). |
| 23 | * |
| 24 | * @param[in] writeCallback Callback that will be triggered when the writer is ready to output some data. |
| 25 | * The callback should copy the provided data into its own buffer. |
| 26 | * @param[in] sampleRate Determines how many samples per second the written data will have. |
| 27 | * @param[in] bitDepth Determines the size of a single sample, in bits. |
| 28 | * @param[in] numChannels Determines the number of audio channels. Channel data will be output interleaved |
| 29 | * in the output buffer. |
| 30 | */ |
| 31 | bool open(std::function<void(UINT8*, UINT32)> writeCallback, UINT32 sampleRate, UINT32 bitDepth, UINT32 numChannels); |
| 32 | |
| 33 | /** |
| 34 | * Writes a new set of samples and converts them to Ogg Vorbis. |
| 35 | * |
| 36 | * @param[in] samples Samples in PCM format. 8-bit samples should be unsigned, but higher bit depths signed. |
| 37 | * Each sample is assumed to be the bit depth that was provided to the open() method. |
| 38 | * @param[in] numSamples Number of samples to encode. |
| 39 | */ |
| 40 | void write(UINT8* samples, UINT32 numSamples); |
| 41 | |
| 42 | /** |
| 43 | * Flushes the last of the data into the write buffer (triggers the write callback). This is called automatically |
| 44 | * when the writer is closed or goes out of scope. |
| 45 | */ |
| 46 | void flush(); |
| 47 | |
| 48 | /** |
| 49 | * Closes the encoder and flushes the last of the data into the write buffer (triggers the write callback). This is |
| 50 | * called automatically when the writer goes out of scope. |
| 51 | */ |
| 52 | void close(); |
| 53 | |
| 54 | /** |
| 55 | * Helper method that allows you to quickly convert PCM to Ogg Vorbis data. |
| 56 | * |
| 57 | * @param[in] samples Buffer containing samples in PCM format. All samples should be in signed integer format. |
| 58 | * @param[in] info Meta-data describing the provided samples. |
| 59 | * @param[out] size Number of bytes written to the output buffer. |
| 60 | * @return Buffer containing the encoded samples, allocated using the general allocator. |
| 61 | */ |
| 62 | static UINT8* PCMToOggVorbis(UINT8* samples, const AudioDataInfo& info, UINT32& size); |
| 63 | private: |
| 64 | /** Writes Vorbis blocks into Ogg packets. */ |
| 65 | void writeBlocks(); |
| 66 | |
| 67 | static const UINT32 BUFFER_SIZE = 4096; |
| 68 | |
| 69 | std::function<void(UINT8*, UINT32)> mWriteCallback; |
| 70 | UINT8 mBuffer[BUFFER_SIZE]; |
| 71 | UINT32 mBufferOffset = 0; |
| 72 | UINT32 mNumChannels = 0; |
| 73 | UINT32 mBitDepth = 0; |
| 74 | bool mClosed = true; |
| 75 | |
| 76 | ogg_stream_state mOggState; |
| 77 | vorbis_info mVorbisInfo; |
| 78 | vorbis_dsp_state mVorbisState; |
| 79 | vorbis_block mVorbisBlock; |
| 80 | }; |
| 81 | |
| 82 | /** @} */ |
| 83 | } |
| 84 | |