Created
May 2, 2025 10:56
-
-
Save siddolo/8619bc1f3c87cbd2d7be118e73efd6af to your computer and use it in GitHub Desktop.
Minimal ALSA WAV player
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
gcc -o alsa_player alsa_player.c -lasound | |
./alsa_player /path/to/wave_file.wav | |
Hardcoded wave format: PCM 44.1KHz, Stereo, 16 bit little endian | |
You need asoundlib.h (libasound2-dev) | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <alsa/asoundlib.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; | |
unsigned int sample_rate = 44100; | |
unsigned int channels = 2; | |
int format = SND_PCM_FORMAT_S16_LE; | |
int err; | |
char *buffer; | |
FILE *fp; | |
size_t bytes_read; | |
// Verifica argomenti | |
if (argc != 2) { | |
fprintf(stderr, "Uso: %s <file.wav>\n", argv[0]); | |
return 1; | |
} | |
// Apri file audio | |
fp = fopen(argv[1], "rb"); | |
if (fp == NULL) { | |
perror("Impossibile aprire il file audio"); | |
return 1; | |
} | |
// Salta l'header WAV (44 byte in un WAV standard) | |
// Nota: questo è un approccio semplificato, un parser WAV reale dovrebbe leggere i metadati | |
fseek(fp, 44, SEEK_SET); | |
// Apri device PCM per la riproduzione | |
err = snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0); | |
if (err < 0) { | |
fprintf(stderr, "Impossibile aprire il device PCM: %s\n", snd_strerror(err)); | |
fclose(fp); | |
return 1; | |
} | |
// Alloca struttura hardware params | |
snd_pcm_hw_params_alloca(¶ms); | |
// Imposta i parametri di default | |
err = snd_pcm_hw_params_any(pcm_handle, params); | |
if (err < 0) { | |
fprintf(stderr, "Impossibile configurare i parametri: %s\n", snd_strerror(err)); | |
goto cleanup; | |
} | |
// Imposta accesso di tipo interleaved | |
err = snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); | |
if (err < 0) { | |
fprintf(stderr, "Errore impostazione accesso: %s\n", snd_strerror(err)); | |
goto cleanup; | |
} | |
// Imposta il formato (16-bit little-endian) | |
err = snd_pcm_hw_params_set_format(pcm_handle, params, format); | |
if (err < 0) { | |
fprintf(stderr, "Errore impostazione formato: %s\n", snd_strerror(err)); | |
goto cleanup; | |
} | |
// Imposta i canali (stereo) | |
err = snd_pcm_hw_params_set_channels(pcm_handle, params, channels); | |
if (err < 0) { | |
fprintf(stderr, "Errore impostazione canali: %s\n", snd_strerror(err)); | |
goto cleanup; | |
} | |
// Imposta la frequenza di campionamento | |
err = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &sample_rate, 0); | |
if (err < 0) { | |
fprintf(stderr, "Errore impostazione sample rate: %s\n", snd_strerror(err)); | |
goto cleanup; | |
} | |
// Applica i parametri hardware | |
err = snd_pcm_hw_params(pcm_handle, params); | |
if (err < 0) { | |
fprintf(stderr, "Impossibile impostare i parametri hardware: %s\n", snd_strerror(err)); | |
goto cleanup; | |
} | |
// Ottieni la dimensione dei frame | |
err = snd_pcm_hw_params_get_period_size(params, &frames, 0); | |
if (err < 0) { | |
fprintf(stderr, "Errore nell'ottenere la dimensione dei frame: %s\n", snd_strerror(err)); | |
goto cleanup; | |
} | |
// Calcola la dimensione del buffer (4 byte per frame in stereo 16-bit) | |
size_t buffer_size = frames * channels * 2; /* 2 bytes per sample */ | |
buffer = (char *)malloc(buffer_size); | |
printf("Riproduzione in corso...\n"); | |
// Ciclo di riproduzione | |
while ((bytes_read = fread(buffer, 1, buffer_size, fp)) > 0) { | |
// Se abbiamo letto meno di buffer_size, azzeriamo il resto | |
if (bytes_read < buffer_size) { | |
memset(buffer + bytes_read, 0, buffer_size - bytes_read); | |
} | |
frames = bytes_read / (channels * 2); | |
err = snd_pcm_writei(pcm_handle, buffer, frames); | |
if (err == -EPIPE) { | |
// EPIPE significa underrun | |
fprintf(stderr, "Underrun occurred\n"); | |
snd_pcm_prepare(pcm_handle); | |
} else if (err < 0) { | |
fprintf(stderr, "Errore dalla funzione writei: %s\n", snd_strerror(err)); | |
} else if (err != (int)frames) { | |
fprintf(stderr, "Short write (scritti %d frame invece di %ld)\n", err, frames); | |
} | |
} | |
// Aspetta che tutto l'audio sia stato riprodotto | |
snd_pcm_drain(pcm_handle); | |
printf("Riproduzione completata.\n"); | |
free(buffer); | |
cleanup: | |
snd_pcm_close(pcm_handle); | |
fclose(fp); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment