Created
September 25, 2024 23:45
-
-
Save bitristan/52c35b57edc09b419e6aa13b863ccd83 to your computer and use it in GitHub Desktop.
convert pcm to ogg opus
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <opusenc.h> | |
#include <vector> | |
#include <fstream> | |
#include <iostream> | |
std::vector<unsigned char> readFile(const std::string &filename) { | |
std::ifstream file(filename, std::ios::binary | std::ios::ate); | |
if (!file.is_open()) { | |
throw std::runtime_error("Failed to open file: " + filename); | |
} | |
std::streamsize size = file.tellg(); | |
file.seekg(0, std::ios::beg); | |
std::vector<unsigned char> buffer(size); | |
if (!file.read(reinterpret_cast<char *>(buffer.data()), size)) { | |
throw std::runtime_error("Failed to read file: " + filename); | |
} | |
return buffer; | |
} | |
void writeFile(const std::string &filename, const std::vector<unsigned char> &data) { | |
std::ofstream file(filename, std::ios::binary); | |
if (!file.is_open()) { | |
throw std::runtime_error("Failed to open file: " + filename); | |
} | |
if (!file.write(reinterpret_cast<const char *>(data.data()), data.size())) { | |
throw std::runtime_error("Failed to write file: " + filename); | |
} | |
} | |
std::vector<unsigned char> encodeToOgg(const std::vector<unsigned char> &pcmData, int sampleRate, int channels) { | |
OggOpusComments *comments = ope_comments_create(); | |
if (comments == nullptr) { | |
throw std::runtime_error("Failed to create Opus comments."); | |
} | |
int error; | |
OggOpusEnc *enc = ope_encoder_create_pull(comments, sampleRate, channels, 0, &error); | |
if (error != OPE_OK) { | |
ope_comments_destroy(comments); | |
throw std::runtime_error("ope encoder create pull error: " + std::string(ope_strerror(error))); | |
} | |
if (ope_encoder_write(enc, reinterpret_cast<const opus_int16 *>(pcmData.data()), pcmData.size() / (2 * channels)) != OPE_OK) { | |
ope_encoder_destroy(enc); | |
ope_comments_destroy(comments); | |
throw std::runtime_error("Failed to write PCM data to encoder."); | |
} | |
if (ope_encoder_drain(enc) != OPE_OK) { | |
ope_encoder_destroy(enc); | |
ope_comments_destroy(comments); | |
throw std::runtime_error("Failed to drain encoder."); | |
} | |
std::vector<unsigned char> buffer; | |
while (true) { | |
unsigned char *page; | |
opus_int32 page_size; | |
int result = ope_encoder_get_page(enc, &page, &page_size, 0); | |
if (result == 0) { | |
break; | |
} | |
buffer.insert(buffer.end(), page, page + page_size); | |
} | |
ope_encoder_destroy(enc); | |
ope_comments_destroy(comments); | |
return buffer; | |
} | |
int main() { | |
try { | |
std::vector<unsigned char> pcmData = readFile("input.pcm"); | |
int sampleRate = 16000; | |
int channels = 1; | |
std::vector<unsigned char> oggData = encodeToOgg(pcmData, sampleRate, channels); | |
writeFile("output.ogg", oggData); | |
std::cout << "Conversion successful. Output saved to output.ogg" << std::endl; | |
} catch (const std::exception &e) { | |
std::cerr << "Error: " << e.what() << std::endl; | |
return 1; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment