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 ", size);


    while (1)
    {
        ret = fread(buffer, 1, size, fp);
        if(ret == 0)
        {
            fprintf(stderr, "end of file on input ");
            break;
        }


        while(ret = snd_pcm_writei(playback_handle, buffer, frames)<0)
        {
            usleep(2000);
            if (ret == -EPIPE)
            {
                /* EPIPE means underrun */
                fprintf(stderr, "underrun occurred ");
                snd_pcm_prepare(playback_handle);
            }
            else if (ret < 0)
            {
                fprintf(stderr, "error from writei: %s ", 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 ", size);


    while (1)
    {
        ret = fread(buffer, 1, size, fp);
        if(ret == 0)
        {
            fprintf(stderr, "end of file on input ");
            break;
        }
        while(ret = snd_pcm_writei(playback_handle, buffer, frames)<0)
        {
            usleep(2000);
            if (ret == -EPIPE)
            {
                /* EPIPE means underrun */
                fprintf(stderr, "underrun occurred ");
                snd_pcm_prepare(playback_handle);
            }
            else if (ret < 0)
            {
                fprintf(stderr, "error from writei: %s ", 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] ");
        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) in multithreading?


thanks,
-Tao







_______________________________________________
Alsa-user mailing list
Alsa-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/alsa-user

Reply via email to