1

I am using alsa-lib-1.2.9 in my embedded Linux system, and now I want to play multiple audio from different threads, so I googled internet (I am NOT familiar with ALSA) and found I can use dmix.

Here is the main part of my /etc/asound.conf in the board.

pcm.!default { type asym playback.pcm "play_softvol" capture.pcm "cap_chn0" } pcm.play_softvol { type softvol slave { pcm play_chn0 } control { name "Speaker Volume" } min_dB -60.0 max_dB -10.0 resolution 50 } pcm.play_chn0 { type plug slave { pcm dmixer } } pcm.dmixer { type dmix ipc_key 77235 ipc_key_add_uid true slave { pcm "hw:0,0" period_time 0 period_size 320 buffer_size 2560 rate 32000 } } ctl.dmixer { type hw card 0 } pcm.cap_chn0 { type plug slave { pcm dsnooper } } pcm.tloop_cap { type plug slave.pcm "hw:Loopback,0,0" } pcm.dsnooper { type dsnoop ipc_key 77236 ipc_key_add_uid true slave { pcm "hw:0,0" channels 4 rate 16000 } bindings { 0 0 1 1 2 2 3 3 } } ctl.dsnooper { type hw card 0 } 

I think the default device is using play_softvol->play_chn0->dmix. So I tried to play 2 PCM files as follows,

#include <stdio.h> #include <stdlib.h> #include <alsa/asoundlib.h> #include <pthread.h> pthread_t tid, tid2; static snd_pcm_t *playback_handle; static int size; static snd_pcm_uframes_t frames; void *play_func(void *arg) { char *buffer; int ret; FILE *fp = fopen(arg, "rb"); if(fp == NULL) return 0; buffer = (char *) malloc(size); fprintf(stderr, "size = %d\n", size); while (1) { ret = fread(buffer, 1, size, fp); if(ret == 0) { fprintf(stderr, "end of file on input\n"); break; } while(ret = snd_pcm_writei(playback_handle, buffer, frames)<0) { usleep(2000); if (ret == -EPIPE) { /* EPIPE means underrun */ fprintf(stderr, "underrun occurred\n"); snd_pcm_prepare(playback_handle); } else if (ret < 0) { fprintf(stderr, "error from writei: %s\n", snd_strerror(ret)); } } } free(buffer); return NULL; } void *play_func2(void *arg) { char *buffer; int ret; FILE *fp = fopen(arg, "rb"); if(fp == NULL) return 0; buffer = (char *) malloc(size); fprintf(stderr, "size = %d\n", size); while (1) { ret = fread(buffer, 1, size, fp); if(ret == 0) { fprintf(stderr, "end of file on input\n"); break; } while(ret = snd_pcm_writei(playback_handle, buffer, frames)<0) { usleep(2000); if (ret == -EPIPE) { /* EPIPE means underrun */ fprintf(stderr, "underrun occurred\n"); snd_pcm_prepare(playback_handle); } else if (ret < 0) { fprintf(stderr, "error from writei: %s\n", snd_strerror(ret)); } } } free(buffer); return NULL; } int main(int argc, char *argv[]) { int ret; int dir=0; snd_pcm_uframes_t periodsize; snd_pcm_hw_params_t *hw_params; if (argc < 2) { printf("error: alsa_play_test [music name] [2nd name]\n"); exit(1); } //1. ret = snd_pcm_open(&playback_handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (ret < 0) { perror("snd_pcm_open"); exit(1); } ....... ret = pthread_create(&tid, NULL, play_func, argv[1]); if (argc > 2) ret = pthread_create(&tid2, NULL, play_func2, argv[2]); pthread_join(tid, NULL); if (argc > 2) pthread_join(tid2, NULL); snd_pcm_close(playback_handle); return 0; } 
asound_threads 1.pcm 2.pcm play song 1.pcm and 2.pcm size = 320 size = 320 

But it sounds messy, the two PCMs are played in an interleaved way, but the speed is wrong and flittered.

So in my case, how can I play multiple audios (audio mixing)?

1 Answer 1

0

I found the right way to play multiple audios in multi-threading system. Each thread should initialize its own PCM handle, and use its own handle to play audio.
It should NOT use a common/shared PCM handle for multi-threads to play audios.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.