2015-01-06 10 views
7

Der Versuch, die ALSA-Audio-Layer zu lernen, um eventuell einen ALSA-Gerätetreiber für die Raspberry Pi-Plattform zu schreiben. Als erstes habe ich verschiedene Samples von der ALSA-Projektseite und anderen Online-Quellen zusammengeklebt, um die einfachste Sache zu machen: Eine WAV-Datei lesen und auf dem Standard-Sound-Gerät abspielen. Ich kann dieses einfache C-Sample nicht zum Laufen bringen.ALSA-Anwendung zum Lesen und Abspielen einer WAV-Datei auf dem Raspberry Pi

Ich benutze libsndfile, um alle WAV-Datei lesen/Header-Decodierung zu tun. Ich verifizierte, dass die Proben, die ich in den Puffer gelesen habe, korrekt sind (verifizierte erste 400K-Proben von dem, was das Programm gegen die Anwendung sndfile-to-text einliest, die die Beispielwerte in eine Textdatei ablegt). Also weiß ich, dass mein Puffer die richtigen Daten enthält, das Problem muss in der Art liegen, wie ich es an die ALSA-APIs weitergebe.

Wenn es ausgeführt wird, produziert es nur im rechten Kanal Sound und verzerrt/matschig - kaum erkennbar. BTW, die "aplay" -Anwendung spielt die gleiche WAV-Datei perfekt und meldet die Datei ist 16-Bit-LE, 44100Hz, Stereo, was entspricht, was meine Anwendung auch berichtet. Laufen Sie dies auf einem Raspberry Pi.

Ich habe das C-Programm hier auf ein Minimum reduziert, um Speicherplatz zu sparen, aber ich habe die korrekten Rückgabecodes von allen API-Aufrufen überprüft. Warum produziert diese einfache ALSA-Anwendung nicht den richtigen Sound?

#include <alsa/asoundlib.h> 
#include <stdio.h> 
#include <sndfile.h> 

#define PCM_DEVICE "default" 

int main(int argc, char **argv) { 

    snd_pcm_t *pcm_handle; 
    snd_pcm_hw_params_t *params; 
    snd_pcm_uframes_t frames; 
    int dir, pcmrc; 

    char *infilename = "/home/pi/shortsample.wav"; 
    int* buf = NULL; 
    int readcount; 

    SF_INFO sfinfo; 
    SNDFILE *infile = NULL; 

    infile = sf_open(infilename, SFM_READ, &sfinfo); 
    fprintf(stderr,"Channels: %d\n", sfinfo.channels); 
    fprintf(stderr,"Sample rate: %d\n", sfinfo.samplerate); 
    fprintf(stderr,"Sections: %d\n", sfinfo.sections); 
    fprintf(stderr,"Format: %d\n", sfinfo.format); 

    /* Open the PCM device in playback mode */ 
    snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0); 

    /* Allocate parameters object and fill it with default values*/ 
    snd_pcm_hw_params_alloca(&params); 
    snd_pcm_hw_params_any(pcm_handle, params); 
    /* Set parameters */ 
    snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); 
    snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE); 
    snd_pcm_hw_params_set_channels(pcm_handle, params, sfinfo.channels); 
    snd_pcm_hw_params_set_rate(pcm_handle, params, sfinfo.samplerate, 0); 

    /* Write parameters */ 
    snd_pcm_hw_params(pcm_handle, params); 

    /* Allocate buffer to hold single period */ 
    snd_pcm_hw_params_get_period_size(params, &frames, &dir); 
    fprintf(stderr,"# frames in a period: %d\n", frames); 

    fprintf(stderr,"Starting read/write loop\n"); 
    buf = malloc(frames * sfinfo.channels * sizeof(int)); 
    while ((readcount = sf_readf_int(infile, buf, frames))>0) { 

     pcmrc = snd_pcm_writei(pcm_handle, buf, readcount); 
     if (pcmrc == -EPIPE) { 
      fprintf(stderr, "Underrun!\n"); 
      snd_pcm_prepare(pcm_handle); 
     } 
     else if (pcmrc < 0) { 
      fprintf(stderr, "Error writing to PCM device: %s\n", snd_strerror(pcmrc)); 
     } 
     else if (pcmrc != readcount) { 
      fprintf(stderr,"PCM write difffers from PCM read.\n"); 
     } 

    } 
    fprintf(stderr,"End read/write loop\n"); 

    snd_pcm_drain(pcm_handle); 
    snd_pcm_close(pcm_handle); 
    free(buf); 

    return 0; 
} 

Antwort

4

Sie müssen überprüfen Sie die Rückgabewerte aller snd_ Funktionen, die ausfallen könnten.

Das S16_LE Format hat zwei Bytes pro Beispiel, aber int hat vier. Verwenden Sie stattdessen short und sf_readf_short.

+0

Mein realer Code überprüft alle Rückgabewerte, ich habe ihn einfach gekürzt. Wechsel von int zu kurz behoben, der WAV spielt nun richtig ... danke! –