#pragma once #include #include #include #include #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) class OpusFileWriter { public: OpusFileWriter() { } ~OpusFileWriter() { assert(!m_Enc); } void Init(const char* file, uint32_t sampleRate) { assert(!m_Enc); m_Samples = 0; m_Comments = ope_comments_create(); int error; m_Enc = ope_encoder_create_file(file, m_Comments, sampleRate, 1, 0, &error); assert(error == 0); ope_encoder_ctl(m_Enc, OPUS_SET_DTX(1)); } void Close() { if(!m_Enc) return; ope_encoder_drain(m_Enc); ope_encoder_destroy(m_Enc); ope_comments_destroy(m_Comments); m_Enc = nullptr; m_Comments = nullptr; } void WriteSamples(const int16_t* samples, uint32_t numSamples) { if(!m_Enc) return; ope_encoder_write(m_Enc, samples, numSamples); m_Samples += numSamples; } void PadSilence(uint32_t numSamples) { if(!m_Enc || m_Samples >= numSamples) return; static const int16_t silence[128] = {0}; uint32_t pad = numSamples - m_Samples; while(pad > 0) { const int samples = MIN(sizeof(silence) / bytesPerSample, pad); ope_encoder_write(m_Enc, silence, samples); pad -= samples; } m_Samples = numSamples; } private: OggOpusComments *m_Comments = nullptr; OggOpusEnc *m_Enc = nullptr; uint32_t m_Samples = 0; static const uint32_t bytesPerSample = 2; };