c - 从 pulseaudio 获取音量值

标签 c linux audio pulseaudio

我通过查看各种示例编写了这段代码:Python pulseaudio monitor , Pavumeter source , async playback example , 和 Pacat source .

我已成功连接到接收器并能够记录它,但我的问题是,我无法获取音量值。如果我尝试从读取函数中打印值,我只会在一秒钟的时间间隔内得到一堆随机数。

现在我不是要别人帮我写完代码,我只是想要一些提示,帮助我朝着正确的方向前进。如何检索音量值?

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <pulse/pulseaudio.h>

static int latency = 20000; // start latency in micro seconds
static int sampleoffs = 0;
static short sampledata[300000];
static pa_buffer_attr bufattr;
static int underflows = 0;
static pa_sample_spec ss;

// This callback gets called when our context changes state.  We really only
// care about when it's ready or if it has failed
void pa_state_cb(pa_context *c, void *userdata) {
  pa_context_state_t state;
  int *pa_ready = userdata;
  state = pa_context_get_state(c);
  switch  (state) {
    // These are just here for reference
  case PA_CONTEXT_UNCONNECTED:
  case PA_CONTEXT_CONNECTING:
  case PA_CONTEXT_AUTHORIZING:
  case PA_CONTEXT_SETTING_NAME:
  default:
    break;
  case PA_CONTEXT_FAILED:
  case PA_CONTEXT_TERMINATED:
    *pa_ready = 2;
    break;
  case PA_CONTEXT_READY:
    *pa_ready = 1;
    break;
  }
}

static void stream_read_cb(pa_stream *s, size_t length, void *userdata) {
  const void *data;
  pa_stream_peek(s, &data, &length);
  data = (const unsigned char*) data;
  printf("%u", data);
  pa_stream_drop(s);
}

int main(int argc, char *argv[]) {
  pa_mainloop *pa_ml;
  pa_mainloop_api *pa_mlapi;
  pa_context *pa_ctx;
  pa_stream *recordstream;
  int r;
  int pa_ready = 0;
  int retval = 0;
  unsigned int a;
  double amp;
  int test = 0;

  // Create a mainloop API and connection to the default server
  pa_ml = pa_mainloop_new();
  pa_mlapi = pa_mainloop_get_api(pa_ml);
  pa_ctx = pa_context_new(pa_mlapi, "Simple PA test application");
  pa_context_connect(pa_ctx, NULL, 0, NULL);

  // This function defines a callback so the server will tell us it's state.
  // Our callback will wait for the state to be ready.  The callback will
  // modify the variable to 1 so we know when we have a connection and it's
  // ready.
  // If there's an error, the callback will set pa_ready to 2
  pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready);

  // We can't do anything until PA is ready, so just iterate the mainloop
  // and continue
  while (pa_ready == 0) {
    pa_mainloop_iterate(pa_ml, 1, NULL);
  }

  if (pa_ready == 2) {
    retval = -1;
    goto exit;
  }

  ss.rate = 44100;
  ss.channels = 2;
  ss.format = PA_SAMPLE_U8;
  recordstream = pa_stream_new(pa_ctx, "Record", &ss, NULL);
  if (!recordstream) {
    printf("pa_stream_new failed\n");
  }

  pa_stream_set_read_callback(recordstream, stream_read_cb, NULL);
  r = pa_stream_connect_record(recordstream, NULL, NULL, PA_STREAM_PEAK_DETECT);

  if (r < 0) {
    printf("pa_stream_connect_playback failed\n");
    retval = -1;
    goto exit;
  }

  // Run the mainloop until pa_mainloop_quit() is called
  // (this example never calls it, so the mainloop runs forever).
  // printf("%s", "Running Loop");
  pa_mainloop_run(pa_ml, NULL);

exit:
  // clean up and disconnect
  pa_context_disconnect(pa_ctx);
  pa_context_unref(pa_ctx);
  pa_mainloop_free(pa_ml);
  return retval;
}

最佳答案

查看来自 UNIX.StackExchange 的原始问题,看起来您正在尝试创建 VU 表。可以使用 envelope detector 来完成.您必须读取输入值,然后对它们的整流值进行平均。一个简单的包络检测器可以作为一个指数移动平均滤波器来完成。

float level = 0; // Init time
const float alpha = COEFFICIENT; // See below

...

// Inside sample loop
float input_signal = fabsf(get_current_sample());
level = level + alpha * (input_signal - level);

这里,alpha是滤波器系数,可以计算为:

const float alpha = 1.0 - expf( (-2.0 * M_PI) / (TC * SAMPLE_RATE) );

其中 TC 被称为“时间常数”参数,以秒为单位,它定义了您希望“跟随”信号的速度。设置得太短会使 VU 表非常“颠簸”,设置得太长会错过信号中的瞬变。 10 毫秒是一个很好的起点。

关于c - 从 pulseaudio 获取音量值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44608514/

相关文章:

linux - 从 bash 脚本运行一些命令

c - 为什么我的 ADPCM 解码器似乎在振荡?

c - 如何推广方阵乘法来处理任意维度

具有 C 扩展的 Python 项目 - 结构、导入和测试

linux - 如何为 ubuntu 编写安装脚本

linux - 在不使用 grep -w 的情况下在 QNX 中查找完全匹配项

java - Android上用于waveTable合成的API

javascript - Web Audio API 对于进行比实时更快的音频分析是否有用?

c - fgets 的意外结果

c - 在 10 年的跨度和 1 秒的分辨率下,什么时间戳具有最佳的空间效率?