#include #include #include #include #include #include #include #include #include #define BUFFER_SIZE 4 #define SAMPLE_SIZE 16384 #define AUDIODEV "/dev/dsp" #define STEREO 1 #define SPEED 48000 int audio_fd; struct prodcons { unsigned char *buffer[BUFFER_SIZE]; unsigned int size[BUFFER_SIZE]; int readpos, writepos; sem_t sem_read; sem_t sem_write; }; void init(struct prodcons *b) { int i; int stereo = STEREO; int speed = SPEED; audio_fd = open(AUDIODEV, O_RDWR); if (audio_fd <= 0) { perror("open"); exit(1); } if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1) { perror("SNDCTL_DSP_STEREO"); exit(1); } if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1) { perror("SNDCTL_DSP_SPEED"); exit(1); } for (i=0; ibuffer[i] = (unsigned char *)malloc(SAMPLE_SIZE); b->size[i] = 0; } sem_init(&b->sem_write, 0, BUFFER_SIZE - 1); sem_init(&b->sem_read, 0, 0); b->readpos = 0; b->writepos = 0; } void put(struct prodcons *b, unsigned char *data, unsigned int size) { sem_wait(&b->sem_write); memcpy(b->buffer[b->writepos], data, size); b->size[b->writepos] = size; b->writepos++; if (b->writepos >= BUFFER_SIZE) b->writepos = 0; sem_post(&b->sem_read); } int get(struct prodcons *b, unsigned char *data, unsigned int *size) { sem_wait(&b->sem_read); *size = b->size[b->readpos]; memcpy(data, b->buffer[b->readpos], *size); b->readpos++; if (b->readpos >= BUFFER_SIZE) b->readpos = 0; sem_post(&b->sem_write); return 0; } #define OVER (-1) struct prodcons buffer; void * producer(void *data) { unsigned char audio_rbuf[SAMPLE_SIZE]; unsigned int rbytes; for (;;) { rbytes = read(audio_fd, audio_rbuf, SAMPLE_SIZE); if (rbytes > 0) put(&buffer, audio_rbuf, rbytes); } return NULL; } void * consumer(void *data) { unsigned char audio_wbuf[SAMPLE_SIZE]; unsigned int wbytes; for (;;) { get(&buffer, audio_wbuf, &wbytes); if (wbytes > 0) write(audio_fd, audio_wbuf, wbytes); } return NULL; } int main() { pthread_t th_a, th_b; void *retval; init(&buffer); pthread_create(&th_a, NULL, producer, 0); pthread_create(&th_b, NULL, consumer, 0); pthread_join(th_a, &retval); pthread_join(th_b, &retval); return 0; }