Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用C语言中的libopus对pcm进行编码和解码opus数据_C_Openal_Opus - Fatal编程技术网

使用C语言中的libopus对pcm进行编码和解码opus数据

使用C语言中的libopus对pcm进行编码和解码opus数据,c,openal,opus,C,Openal,Opus,我试图用libopus对来自硬件的传入pcm数据进行编码,然后使用相同的库对其进行解码,但得到的结果是解码。可以使用aplay-t raw--rate=48000--buffer size=1920--channels=1--format=FLOAT\u LE decoded.raw命令播放raw,但它仍然只是一个白噪声测试.raw文件可以使用相同的前一个命令正常播放,没有问题。但是,test.opus文件不能以任何方式播放。不确定我在这里遗漏了什么,数据在test.raw中写得很好,所以我认为

我试图用libopus对来自硬件的传入pcm数据进行编码,然后使用相同的库对其进行解码,但得到的结果是
解码。可以使用
aplay-t raw--rate=48000--buffer size=1920--channels=1--format=FLOAT\u LE decoded.raw
命令播放raw
,但它仍然只是一个白噪声<代码>测试.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);
}
#包括
#包括
#包括
#包括
#包括
#包括
int main(){
FILE*raw=fopen(“test.raw”,“w”);
文件*opus=fopen(“test.opus”,“w”);
文件*decoded=fopen(“decoded.raw”,“w”);
int i=0;
尺寸捕获频率=48000;
大小样本大小=捕获频率/25;
int通道长度=1;
整数误差;
OpuseCoder*encoder=opus\u编码器\u创建(捕获频率,1,opus\u应用程序\u VOIP,&错误);
如果(错误!=OPUS_OK){
fprintf(stderr,“未能创建编解码器”);
}
常量ALCchar*deviceName=alcGetString(空,ALC\u捕获\u默认\u设备\u说明符);
ALCdevice*device=alcCaptureOpenDevice(设备名称、捕获频率、ALU格式、MONO浮点32、样本大小);
如果(设备==NULL){
fprintf(stderr,“无法打开设备”\n);
返回-1;
}
printf(“打开的捕获设备\%s\”\n”,alcGetString(设备,ALC_捕获\默认\设备\说明符));
alcCaptureStart(设备);
OpusDecoder*decoder=opus_decoder_create(捕获频率、通道长度和错误);
如果(错误!=OPUS_OK)
fprintf(stderr,“未能创建解码器”);
而(alcGetError(设备)==ALC\u无错误&&i<1000){
ALCint可用示例=0;
alcGetIntegerv(设备、ALC捕获样本、1和可用样本);
如果(可用样本<样本大小)
持续
float*buffer=(float*)malloc(样本大小*通道长度*大小(float));
AlCaptureSamples(设备、缓冲区、样本大小);
printf(“获得%d个样本,我们需要%d\n”,样本大小,样本大小);
无符号字符*输出=(无符号字符*)malloc(4000);
int bytes_write=opus_encode_float(编码器、缓冲区、样本大小、输出,4000);
如果(写入的字节数小于0){
如果(字节写入==OPUS\U BAD\U参数)
fprintf(stderr,“无效参数”\n);
其他的
fprintf(stderr,“编码失败\n”);
持续
}否则{
printf(“从编码器%d\n获取输出”,写入字节);
}
fwrite(输出,写入字节,1,opus);
浮点*输出×pcm=(浮点*)malloc(样本大小×大小×浮点));
int decoded_bytes=opus_decode_float(解码器、输出、写入字节、输出、pcm、样本大小,1);
如果(解码字节<1)
fprintf(stderr,“解码字节失败\n”);
否则{
printf(“%d字节已解码\n”,已解码\u字节);
}
fwrite(输出pcm,样本大小*sizeof(浮点),1,解码);
fwrite(缓冲区,样本大小*sizeof(浮动),1,原始);
i++;
}
fclose(opus);
fclose(生的);
fclose(解码);
自动捕获停止(装置);
alcCaptureCloseDevice(装置);
opus_解码器_销毁(解码器);
opus_编码器_销毁(编码器);
}

您无法解码file.opus,因为您需要一些用于opus编解码器的容器。这很重要,因为OPUS是面向数据包的格式。所以它不能解码字节流。它可以解码数据包流

当您将数据包一个接一个地写入文件时,您会丢失数据包边界,并且无法恢复它们

您可以选择一种可能的格式:

  • ogg
  • 马特罗斯卡

我认为您可以很容易地找到方便的库来编写它们。

我很好奇,您是否解码了记录到原始缓冲区中的相同字节数?如果你能给这两个文件贴个链接,我很乐意看一看。