0

非常に単純な ogg プレーヤーを実装しようとしています。基本的に ogg ファイルを開き、それを検証し、libvorbisfile デコーダーを介して ALSA PCM に実行します。問題は、サウンド出力が非常に歪んでおり、ラグがあり、元の音楽ファイルを聞くにはかなりの想像力が必要なことです。alsa ファイルと ogg ファイルはどちらも、44100Hz のサンプルレート、2 つのチャンネル、16 ビットのサンプル サイズでエンコードされています。

ソースコードは次のとおりです。

#include <stdio.h>
#include <stdlib.h>
#include <vorbis/vorbisfile.h>
#include <alsa/asoundlib.h>

char *buffer;
static char *device = "default";

int main(int argc, char **argv)
{
    buffer = (char *) malloc(4096);
    int err;
    snd_pcm_t *handle;
    snd_pcm_sframes_t frames;

    if((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0))
            < 0) {
        printf("Playback open error: %s\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    }
    if((err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE,
            SND_PCM_ACCESS_RW_INTERLEAVED, 2, 44100, 1, 500000))
            < 0) { /* 0.5sec */
        printf("Playback open error: %s\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    }

    OggVorbis_File vf;
    int eof = 0;
    int current_section;

    err = ov_fopen("zedd.ogg", &vf);
    if(err != 0) {
        perror("Error opening file");
    } else {
        vorbis_info *vi = ov_info(&vf, -1);
        fprintf(stderr, "Bitstream is %d channel, %ldHz\n",
                vi->channels, vi->rate);
        fprintf(stderr, "Encoded by: %s\n\n",
                ov_comment(&vf, -1)->vendor);

        while(!eof) {
            long ret = ov_read(&vf, buffer, 4096, 0, 2, 1,
                    &current_section);
            if(ret == 0) {
                /* EOF */
                eof = 1;
            } else if(ret < 0) {
                /* error in the stream. */
            } else {
                frames = snd_pcm_writei(handle, buffer, ret);
                snd_pcm_wait(handle, 20000);
                if(frames < 0)
                    frames = snd_pcm_recover(handle, frames,
                            0);
                if(frames < 0) {
                    printf("snd_pcm_writei failed: %s\n",
                            snd_strerror(err));
                    break;
                }
                if(frames > 0 && frames < 4096)
                    printf("Short write (expected %li, wrote %li)\n",
                            ret, frames);
            }
        }
        ov_clear(&vf);
    }

    snd_pcm_close(handle);

    return (0);
}

どんな助けでも本当に役に立ちます。

4

1 に答える 1

1

答えは実にシンプルです。関数snd_pcm_writeiでは、フレーム数ではなく、バッファ内のバイト数を渡していました。16 ビット 2 チャネル オーディオの場合、1 フレーム 4 バイトです (サンプルあたり 2 バイトで、2 つのチャネルがあります)。frames = snd_pcm_writei(handle, buffer, ret/4);snd_pcm_wait の呼び出しを変更して削除すると (ブロッキング モードでは冗長)、すべての問題が修正されます。irc.freenode.net の #xiph にいる人たちに感謝します。

于 2015-09-10T18:30:47.043 に答える