[英]Encoding pcm and decoding opus data using libopus in C
我正在嘗試使用libopus對來自硬件的傳入pcm數據進行編碼,然后使用相同的庫對其進行解碼,但是我得到的結果是已decoded.raw
aplay -t raw --rate=48000 --buffer-size=1920 --channels=1 --format=FLOAT_LE decoded.raw
可以使用aplay -t raw --rate=48000 --buffer-size=1920 --channels=1 --format=FLOAT_LE decoded.raw
命令,但仍然只是白噪聲。 可以使用與先前相同的命令播放test.raw
文件,沒問題。 但是test.opus
文件不能以任何方式播放。 不知道我在這里缺少什么,數據已經在test.raw
寫的很好,所以我認為錄制策略不是問題。
#include <string>
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alext.h>
#include <opus/opus.h>
#include <string.h>
int main() {
FILE* raw = fopen("test.raw", "w");
FILE* opus = fopen("test.opus", "w");
FILE* decoded = fopen("decoded.raw", "w");
int i = 0;
size_t capture_frequency = 48000;
size_t samples_size = capture_frequency/25;
int channels_length = 1;
int error;
OpusEncoder* encoder = opus_encoder_create(capture_frequency, 1, OPUS_APPLICATION_VOIP, &error);
if(error != OPUS_OK){
fprintf(stderr, "failed to create codec\n");
}
const ALCchar* deviceName = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
ALCdevice* device = alcCaptureOpenDevice(deviceName, capture_frequency, AL_FORMAT_MONO_FLOAT32, samples_size);
if(device == NULL) {
fprintf(stderr, "could not open device\n");
return -1;
}
printf("Opened capture device \"%s\"\n", alcGetString(device, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
alcCaptureStart(device);
OpusDecoder* decoder = opus_decoder_create(capture_frequency, channels_length, &error);
if(error != OPUS_OK)
fprintf(stderr, "failed to create decoder\n");
while(alcGetError(device) == ALC_NO_ERROR && i < 1000){
ALCint availableSamples = 0;
alcGetIntegerv(device, ALC_CAPTURE_SAMPLES, 1, &availableSamples);
if(availableSamples < samples_size)
continue;
float* buffer = (float*)malloc(samples_size*channels_length*sizeof(float));
alcCaptureSamples(device, buffer, samples_size);
printf("got %d samples, we needed %d\n", samples_size, samples_size);
unsigned char* output = (unsigned char*) malloc(4000);
int bytes_written = opus_encode_float(encoder, buffer, samples_size, output, 4000);
if(bytes_written < 0){
if(bytes_written == OPUS_BAD_ARG)
fprintf(stderr, "invalid args\n");
else
fprintf(stderr, "failed to encode\n");
continue;
} else {
printf("got output from encoder %d\n", bytes_written);
}
fwrite(output, bytes_written, 1, opus);
float* output_pcm = (float*) malloc(samples_size*sizeof(float));
int decoded_bytes = opus_decode_float(decoder, output, bytes_written, output_pcm, samples_size, 1);
if(decoded_bytes < 1)
fprintf(stderr, "failed to decode bytes\n");
else {
printf("%d bytes decoded\n", decoded_bytes);
}
fwrite(output_pcm, samples_size*sizeof(float), 1, decoded);
fwrite(buffer, samples_size*sizeof(float), 1, raw);
i++;
}
fclose(opus);
fclose(raw);
fclose(decoded);
alcCaptureStop(device);
alcCaptureCloseDevice(device);
opus_decoder_destroy(decoder);
opus_encoder_destroy(encoder);
}
您無法解碼file.opus,因為您需要OPUS編解碼器的某些容器。 這很重要,因為OPUS是面向數據包的格式。 因此,它無法解碼字節流。 它可以解碼數據包流。
當您將數據包一個接一個地寫入文件時,您會松開數據包邊界,無法恢復它們。
您可以選擇一種可能的格式:
我認為您可以輕松地找到方便的庫來編寫它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.