2017-06-17 13 views
2

私はこのコードを、さまざまな例を見て書いた:Python pulseaudio monitorPavumeter sourceasync playback example、およびPacat sourceです。パルス音量から音量を得る

シンクに正常に接続して録音できましたが、私の問題は音量を上げることに固執しています。私がread関数から値を表示しようとすると、ちょうど1秒間隔で乱数が得られます。

私はコードを書くのをやめる人を求めていません。ちょうどいいヒントがありますので、正しい方向に向けることができます。ボリューム値を取得するにはどうすればよいですか?

#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; 
} 
+0

「音量」とは、「オーディオの振幅」または「ユーザーが設定した現在のゲイン値」を意味しますか? –

答えて

0

元の質問を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のように計算することができ、フィルタ係数、次のとおりです。

TCは、あなたが望むどのくらいの速定義秒単位で測定された「時定数」パラメータ、として知られている
const float alpha = 1.0 - expf((-2.0 * M_PI)/(TC * SAMPLE_RATE)); 

信号に「追従する」。それを短すぎるとVUメーターが非常に「くぼんだ」ようになり、長すぎると信号のトランジェントが失われます。 10 mSは良い値です。

関連する問題