首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >C:为什么我的库中的全局变量不会更新?(使用ALSA库)

C:为什么我的库中的全局变量不会更新?(使用ALSA库)
EN

Stack Overflow用户
提问于 2019-05-23 05:11:32
回答 1查看 41关注 0票数 0

前言:我看过其他的答案,我相信这是一个不同类型的问题。这可能与指针有关,但其他答案都没有帮助。我也可能遗漏了一些东西。

我设法使用ALSA库编写了一个将原始音频数据流式传输到stdout的工作程序。我现在正在尝试将这段代码泛化到一个库中,并且库的.c文件中的全局变量没有更新。据我所知,设置与原始程序没有什么不同,所以我认为它应该可以工作……但事实并非如此。如果有人能解释清楚我是怎么把事情搞砸的,我会很感激的。抢先谢谢你!

EDIT 1:

调用wm8782_open_audio()时,wm8782.c顶部的所有全局变量都无法设置。例如,在调用wm8782_open_audio()之后在wm8782_us_to_loops()中调用snd_pcm_hw_params_get_period_time(params, &val, &dir);时,会因为params未初始化而失败。但是,wm8782_open_audio()完成时没有错误!

EDIT 2:

我在我的头中添加了extern声明,没有骰子。有关更新的文件,请参阅下面的内容。

EDIT 3:

我已经在一个没有头文件的C文件中重现了这个问题。简单地将代码分解成函数就足以将其分解。我已经用这个整体的C文件替换了这两个库文件,以消除链接器错误等。

这是我试图将其推广到库中的原始程序。这就像我想要的那样工作。

代码语言:javascript
复制
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>

long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
char *buffer;

int main()
{
    /* Open PCM device for recording (capture). */
    rc = snd_pcm_open(&handle, "hw:1",
                      SND_PCM_STREAM_CAPTURE, 0);
    if (rc < 0)
    {
        fprintf(stderr,
                "unable to open pcm device: %s\n",
                snd_strerror(rc));
        exit(1);
    }

    /* Allocate a hardware parameters object. */
    snd_pcm_hw_params_alloca(&params);

    /* Fill it in with default values. */
    snd_pcm_hw_params_any(handle, params);

    /* Set the desired hardware parameters. */

    /* Interleaved mode */
    snd_pcm_hw_params_set_access(handle, params,
                                 SND_PCM_ACCESS_RW_INTERLEAVED);

    /* Signed 32-bit little-endian format */
    snd_pcm_hw_params_set_format(handle, params,
                                 SND_PCM_FORMAT_S32_LE);

    /* Two channels (stereo) */
    snd_pcm_hw_params_set_channels(handle, params, 2);

    /* 44100 bits/second sampling rate (CD quality) */
    val = 44100;
    snd_pcm_hw_params_set_rate_near(handle, params,
                                    &val, &dir);

    /* Set period size to 64 frames. */
    frames = 64;
    snd_pcm_hw_params_set_period_size_near(handle,
                                           params, &frames, &dir);

    /* Write the parameters to the driver */
    rc = snd_pcm_hw_params(handle, params);
    if (rc < 0)
    {
        fprintf(stderr,
                "unable to set hw parameters: %s\n",
                snd_strerror(rc));
        exit(1);
    }

    /* Use a buffer large enough to hold one period */
    snd_pcm_hw_params_get_period_size(params,
                                      &frames, &dir);
    size = frames * 8; /* 4 bytes/sample, 2 channels */
    buffer = (char *) malloc(size);

    /* We want to loop for 5 seconds */
    snd_pcm_hw_params_get_period_time(params,
                                      &val, &dir);
    //fprintf(stderr, "%u\n", val);
    loops = 5000000 / val;

    while (loops > 0)
    {
        loops--;
        rc = snd_pcm_readi(handle, buffer, frames);
        if (rc == -EPIPE)
        {
            /* EPIPE means overrun */
            fprintf(stderr, "overrun occurred\n");
            snd_pcm_prepare(handle);
        }
        else if (rc < 0)
        {
            fprintf(stderr,
                    "error from read: %s\n",
                    snd_strerror(rc));
        }
        else if (rc != (int)frames)
        {
            fprintf(stderr, "short read, read %d frames\n", rc);
        }
        rc = write(1, buffer, size);
        if (rc != size)
            fprintf(stderr,
                    "short write: wrote %d bytes\n", rc);
    }

    snd_pcm_drain(handle);
    snd_pcm_close(handle);
    free(buffer);

    return 0;
}

现在这里是模块化版本,它最终将成为一个库。对于ERROR: Failed to get number of loops.,此操作失败

代码语言:javascript
复制
#define ALSA_PCM_NEW_HW_PARAMS_API

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <alsa/asoundlib.h>

char *wm8782_buffer;
int wm8782_buffer_size;

snd_pcm_t *wm8782_handle;
snd_pcm_hw_params_t *wm8782_params;
int wm8782_dir;
snd_pcm_uframes_t wm8782_frames;
unsigned int wm8782_val;
int wm8782_rc;

typedef enum
{
    WM8782_READ_OVERRUN,
    WM8782_READ_ERROR,
    WM8782_READ_SHORT,
    WM8782_READ_GOOD,
} wm8782read_t;

typedef enum
{
    WM8782_RATE_8K = 8000,
    WM8782_RATE_16K = 16000,
    WM8782_RATE_32K = 32000,
    WM8782_RATE_44_1K = 44100,
    WM8782_RATE_48K = 48000,
    WM8782_RATE_96K = 96000,
    WM8782_RATE_192K = 192000,
} wm8782rate_t;

bool wm8782_open_audio(wm8782rate_t rate_in, snd_pcm_uframes_t wm8782_frames_in)
{
    // Open PCM device for recording (capture).
    wm8782_rc = snd_pcm_open(&wm8782_handle, "hw:1",
                      SND_PCM_STREAM_CAPTURE, 0);
    if (wm8782_rc < 0)
    {
        fprintf(stderr,
                "ERROR: Unable to open pcm device: %s\n",
                snd_strerror(wm8782_rc));
        return false;
    }

    // Allocate a hardware parameters object.
    snd_pcm_hw_params_alloca(&wm8782_params);

    // Fill it in with default values
    snd_pcm_hw_params_any(wm8782_handle, wm8782_params);

    // Set the desired hardware parameters. */

    // Interleaved mode
    snd_pcm_hw_params_set_access(wm8782_handle, wm8782_params, SND_PCM_ACCESS_RW_INTERLEAVED);

    // Signed 32-bit little-endian format
    snd_pcm_hw_params_set_format(wm8782_handle, wm8782_params, SND_PCM_FORMAT_S32_LE);

    // Two channels (stereo)
    snd_pcm_hw_params_set_channels(wm8782_handle, wm8782_params, 2);

    // Set rate
    wm8782_val = rate_in;
    snd_pcm_hw_params_set_rate_near(wm8782_handle, wm8782_params, &wm8782_val, &wm8782_dir);

    // Set period size.
    wm8782_frames = wm8782_frames_in;
    snd_pcm_hw_params_set_period_size_near(wm8782_handle, wm8782_params, &wm8782_frames, &wm8782_dir);

    // Write the parameters to the driver
    wm8782_rc = snd_pcm_hw_params(wm8782_handle, wm8782_params);
    if (wm8782_rc < 0)
    {
        fprintf(stderr,
                "ERROR: Unable to set hw parameters: %s\n",
                snd_strerror(wm8782_rc));
        return false;
    }

    // Use a buffer large enough to hold one period
    snd_pcm_hw_params_get_period_size(wm8782_params, &wm8782_frames, &wm8782_dir);
    wm8782_buffer_size = wm8782_frames * 8; // 4 bytes/sample, 2 channels
    wm8782_buffer = (char *) malloc(wm8782_buffer_size);

    return true;
}

void wm8782_close_audio()
{
    snd_pcm_drain(wm8782_handle);
    snd_pcm_close(wm8782_handle);
    free(wm8782_buffer);
}

wm8782read_t wm8782_read_audio()
{
    wm8782_rc = snd_pcm_readi(wm8782_handle, wm8782_buffer, wm8782_frames);
    if (wm8782_rc == -EPIPE)
    {
        // EPIPE means overrun
        fprintf(stderr, "ERROR: Overrun occurred\n");
        snd_pcm_prepare(wm8782_handle);
        return WM8782_READ_OVERRUN;
    }
    else if (wm8782_rc < 0)
    {
        fprintf(stderr, "ERROR: From read: %s\n", snd_strerror(wm8782_rc));
        return WM8782_READ_ERROR;
    }
    else if (wm8782_rc != (int)wm8782_frames)
    {
        fprintf(stderr, "ERROR: Short read, read %d wm8782_frames\n", wm8782_rc);
        return WM8782_READ_SHORT;
    }

    return WM8782_READ_GOOD;
}

unsigned int wm8782_us_to_loops(unsigned int us_in)
{
    if(snd_pcm_hw_params_get_period_time(wm8782_params, &wm8782_val, &wm8782_dir) < 0)
    {
        fprintf(stderr, "ERROR: Failed to get number of loops.\n");
        return 0;
    }
    //fprintf(stderr, "%u\n", wm8782_val);
    return (us_in / wm8782_val);
}

int main()
{
    if(!wm8782_open_audio(44100, 64))
    {
        fprintf(stderr, "unable to open pcm device");
    }

    unsigned int loops =  wm8782_us_to_loops(5000000);

    while (loops > 0)
    {
        loops--;
        wm8782_read_audio();

        wm8782_rc = write(1, wm8782_buffer, wm8782_buffer_size);
        if (wm8782_rc != wm8782_buffer_size)
            fprintf(stderr,
                    "short write: wrote %d bytes\n", wm8782_rc);
    }

    wm8782_close_audio();

    return 0;
}
EN

回答 1

Stack Overflow用户

发布于 2019-05-23 07:16:09

好的,事实证明这根本不是一个全球性的问题…抱歉,各位!它是传递给snd_pcm_hw_params_get_period_size()的一些奇怪的无效参数。代码实际上使用了手动定义的循环数量,所以我要结束这个问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56265081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档