dm365下面的音频回放程序/*******************************************************************************
**+--------------------------------------------------------------------------+**
**| **** |**
**| **** |**
**| ******o*** |**
**| ********_///_**** |**
**| ***** /_//_/ **** |**
**| ** ** (__/ **** |**
**| ********* |**
**| **** |**
**| *** |**
**| |**
**| Copyright (c) 1998-2004 Texas Instruments Incorporated |**
**| ALL RIGHTS RESERVED |**
**| |**
**| Permission is hereby granted to licensees of Texas Instruments |**
**| Incorporated (TI) products to use this computer program for the sole |**
**| purpose of implementing a licensee product based on TI products. |**
**| No other rights to reproduce, use, or disseminate this computer |**
**| program, whether in part or in whole, are granted. |**
**| |**
**| TI makes no representation or warranties with respect to the |**
**| performance of this computer program, and specifically disclaims |**
**| any responsibility for any damages, special or consequential, |**
**| connected with the use of this program. |**
**| |**
**+--------------------------------------------------------------------------+**
*******************************************************************************/
/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
#include<stdio.h>
#include<fcntl.h>
#include<pthread.h>
#include<semaphore.h>
#include<errno.h>
#include<string.h>
#include<sys/ioctl.h>
#include<linux/soundcard.h>
#include<poll.h>
#define PLAYBACK 0
#define CAPTURE 1
int rc;
int buffer_size;
snd_pcm_t *handle[2];
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
pthread_t recorder_thread, player_thread;
int pipe_desc[2];
void *recorder(void *arg);
void *player(void *arg);
int main()
{
int i = 0;
if (pipe(pipe_desc)) {
printf("audio_loopback: unable to create pipe\n");
exit(0);
}
/* Open PCM device for playback. */
rc = snd_pcm_open(&handle[PLAYBACK], "default",
SND_PCM_STREAM_PLAYBACK, 0);
if (rc < 0) {
printf("audio_loopback: unable to open pcm device: %s\n", snd_strerror(rc));
exit(1);
}
/* Open PCM device for record. */
rc = snd_pcm_open(&handle[CAPTURE], "default",
SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0) {
printf("audio_loopback: unable to open pcm device: %s\n", snd_strerror(rc));
exit(1);
}
for (i = 0; i < 2; i++) {
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(¶ms);
/* Fill it in with default values. */
snd_pcm_hw_params_any(handle[i], params);
/* Set the desired hardware parameters. */
/* Interleaved mode */
snd_pcm_hw_params_set_access(handle[i], params,
SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle[i], params,
SND_PCM_FORMAT_S16_LE);
/* Two channels (stereo) */
snd_pcm_hw_params_set_channels(handle[i], params, 2);
/* 44100 bits/second sampling rate (CD quality) */
val = 44100;
snd_pcm_hw_params_set_rate_near(handle[i], params, &val, &dir);
/* Set period size */
frames = 1024;
snd_pcm_hw_params_set_period_size_near(handle[i],
params, &frames, &dir);
/* Write the parameters to the driver */
rc = snd_pcm_hw_params(handle[i], params);
if (rc < 0) {
printf("audio_loopback: unable to set hw parameters: %s\n", snd_strerror(rc));
exit(1);
}
}
/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
buffer_size = frames * 4; /* 2 bytes/sample, 2 channels */
pthread_create(&recorder_thread, NULL, recorder, NULL);
pthread_create(&player_thread, NULL, player, NULL);
pthread_join(recorder_thread, NULL);
pthread_join(player_thread, NULL);
printf("audio_loopback: Both threads are exited...\n");
return 0;
}
void *recorder(void *arg)
{
unsigned char *buffer;
buffer = (unsigned char *)malloc(buffer_size);
if (!buffer) {
printf("audio_loopback: could not allocate memory for the recorder audio buffer\n");
goto recorder_thread_exit;
}
rc = 0;
while(1) {
rc = snd_pcm_readi(handle[CAPTURE], buffer, frames);
if (rc == -EAGAIN)
continue;
if (rc == -EPIPE) {
/* EPIPE means overrun */
printf("audio_loopback: overrun occurred\n");
snd_pcm_prepare(handle[CAPTURE]);
/*snd_pcm_recover(handle[CAPTURE], rc, 0);*/
} else if (rc < 0) {
printf("audio_loopback: error from read: %s\n", snd_strerror(rc));
} else if (rc != (int)frames) {
printf("audio_loopback: short read, read %d frames\n", rc);
}
if (write(pipe_desc[1], buffer, buffer_size) != buffer_size) {
printf("audio_loopback: error writing to the pipe\n");
break;
}
}
recorder_thread_exit:
printf("audio_loopback: recorder thread exited\n");
free(buffer);
pthread_exit(0);
}
void *player(void *arg)
{
unsigned char *buffer;
buffer = (unsigned char *)malloc(buffer_size);
if (!buffer) {
printf("audio_loopback: could not allocate memory for the player audio buffer\n");
goto player_thread_exit;
}
rc = 0;
while(1){
if (read(pipe_desc[0], buffer, buffer_size) != buffer_size) {
printf("audio_loopback: error reading from the pipe\n");
break;
}
rc = snd_pcm_writei(handle[PLAYBACK], buffer, frames);
if (rc == -EAGAIN)
continue;
if (rc == -EPIPE) {
/* EPIPE means underrun */
printf("audio_loopback: underrun occurred\n");
snd_pcm_prepare(handle[PLAYBACK]);
/*snd_pcm_recover(handle[PLAYBACK], rc, 0);*/
} else if (rc < 0) {
printf("audio_loopback: error from writei: %s\n", snd_strerror(rc));
} else if (rc != (int)frames) {
printf("audio_loopback: short write, write %d frames\n", rc);
}
}
player_thread_exit:
printf("audio_loopback: player thread exited...\n");
free(buffer);
pthread_exit(0);
} |