You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Sox在C语言中播放音频文件无输出问题求助

使用Sox播放音频无输出的问题排查与修复

我目标是编写一个应用程序,用来查找、打开音频文件并通过Sox播放,但目前遇到了无法输出音频的问题。我参考并修改了一些示例代码,但仍然没有声音。我仅对原示例做了少量修改:从main函数创建实例并传递指针,在函数中指定实际的数据文件(测试时用了本地的示例文件,暂时没做文件搜索功能)。除非必要,我不想对输入文件添加任何效果处理。

以下是我当前的代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include "sox.h"

typedef struct State {
    sox_format_t *sox_in;
    sox_format_t *sox_out;
    sox_effects_chain_t *sox_chain;

} State;


State *sm;

void init_player(sox_format_t* sxin, sox_format_t* sxout, sox_effects_chain_t* sxchain)
{
    sm  = (struct State*)malloc(sizeof(struct State));
    sm->sox_in = sxin;
    sm->sox_out = sxout;
    sm->sox_chain = sxchain;
}

void play(State* s)
{
    sm->sox_in = sox_open_read("/home/me/Music/sox_out1.flac", NULL, NULL, NULL);
    printf("successful read\n");
    sm->sox_in = sox_open_write("default", &(sm->sox_in)->signal, NULL, "alsa", NULL, NULL);
    printf("successful write\n");
    sm->sox_chain = sox_create_effects_chain(&(sm->sox_in)->encoding, &(sm->sox_out)->encoding);
    printf("chain created\n");
    printf("starting to flow effects\n");           
    sox_flow_effects(sm->sox_chain, NULL, NULL);
    printf("successful flow\n"); 
    sox_delete_effects_chain(sm->sox_chain);
    sox_close(sm->sox_out);
    sox_close(sm->sox_in);
}


int main() {
    static sox_format_t *in, *out; /* input and output files */
    static sox_effects_chain_t *chain;

    assert(sox_init() == SOX_SUCCESS);

    init_player(in, out, chain);

    play(sm);
}

问题点分析

  1. 输入指针被覆盖:play函数中打开输入文件后,立刻用sox_open_write的结果覆盖了sm->sox_in,导致原输入文件指针丢失,根本无法读取音频数据。
  2. 缺少必要的效果节点:Sox的效果链必须包含输入、输出节点来完成数据流转,空的效果链无法传递音频数据到设备。
  3. 无错误检查:没有判断sox_open_read、sox_open_write等关键函数的返回值,可能隐藏了文件不存在、设备无法打开等错误。
  4. 结构体逻辑混乱:play函数传入了s参数却未使用,直接操作全局变量sm,逻辑冗余且易出问题。

修复后的代码

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include "sox.h"

typedef struct State {
    sox_format_t *sox_in;
    sox_format_t *sox_out;
    sox_effects_chain_t *sox_chain;
} State;

// 初始化播放器实例
State* init_player(void)
{
    State *sm = malloc(sizeof(State));
    if (!sm) {
        perror("Failed to allocate State");
        return NULL;
    }
    sm->sox_in = NULL;
    sm->sox_out = NULL;
    sm->sox_chain = NULL;
    return sm;
}

// 播放音频文件
int play(State* s, const char* audio_path)
{
    if (!s) {
        fprintf(stderr, "Invalid State pointer\n");
        return -1;
    }

    // 打开输入音频文件
    s->sox_in = sox_open_read(audio_path, NULL, NULL, NULL);
    if (!s->sox_in) {
        fprintf(stderr, "Failed to open input file: %s\n", audio_path);
        return -1;
    }
    printf("Successfully opened input file\n");

    // 打开ALSA输出设备
    s->sox_out = sox_open_write("default", &s->sox_in->signal, NULL, "alsa", NULL, NULL);
    if (!s->sox_out) {
        fprintf(stderr, "Failed to open ALSA output device\n");
        sox_close(s->sox_in);
        return -1;
    }
    printf("Successfully opened output device\n");

    // 创建效果链
    s->sox_chain = sox_create_effects_chain(&s->sox_in->encoding, &s->sox_out->encoding);
    if (!s->sox_chain) {
        fprintf(stderr, "Failed to create effects chain\n");
        sox_close(s->sox_out);
        sox_close(s->sox_in);
        return -1;
    }
    printf("Effects chain created\n");

    // 添加输入效果(从输入文件读取数据)
    sox_effect_t *eff = sox_create_effect(sox_find_effect("input"));
    char *args[] = {(char*)s->sox_in, NULL};
    sox_effect_options(eff, 1, args);
    sox_add_effect(s->sox_chain, eff, &s->sox_in->signal, &s->sox_in->signal);
    free(eff);

    // 添加输出效果(写入到输出设备)
    eff = sox_create_effect(sox_find_effect("output"));
    args[0] = (char*)s->sox_out;
    sox_effect_options(eff, 1, args);
    sox_add_effect(s->sox_chain, eff, &s->sox_in->signal, &s->sox_out->signal);
    free(eff);

    // 流转音频数据
    printf("Starting audio playback...\n");
    int ret = sox_flow_effects(s->sox_chain, NULL, NULL);
    if (ret != SOX_SUCCESS) {
        fprintf(stderr, "Failed to flow effects\n");
    } else {
        printf("Playback completed successfully\n");
    }

    // 清理资源
    sox_delete_effects_chain(s->sox_chain);
    sox_close(s->sox_out);
    sox_close(s->sox_in);

    return ret;
}

int main() {
    assert(sox_init() == SOX_SUCCESS);

    State* player = init_player();
    if (!player) {
        sox_quit();
        return EXIT_FAILURE;
    }

    play(player, "/home/me/Music/sox_out1.flac");

    free(player);
    sox_quit(); // 清理Sox库资源
    return EXIT_SUCCESS;
}

关键修复说明

  1. 保留输入指针:分开存储输入文件和输出设备的指针,避免覆盖导致的数据源丢失。
  2. 添加核心效果节点:通过input和output效果节点搭建数据流转通道,这是Sox播放音频的必要逻辑。
  3. 增加错误检查:对所有关键函数的返回值做判断,便于快速定位问题。
  4. 优化实例管理:去掉全局变量,改为通过函数返回实例指针,逻辑更清晰。
  5. 补充资源清理:在程序结束时调用sox_quit(),正确释放Sox库占用的资源。

内容的提问来源于stack exchange,提问作者eh_whatever

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.07 10:04:49