|
|
|
/*
|
|
|
|
|
|
|
|
Copyright (C) 2003 Stefan Westerfeld
|
|
|
|
stefan@space.twc.de
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is a threaded example using the aRts C API.
|
|
|
|
*
|
|
|
|
* Compile programs using the aRts C API with
|
|
|
|
*
|
|
|
|
* cc -o artscmt artscmt.c `artsc-config --cflags` `artsc-config --libs`
|
|
|
|
*
|
|
|
|
* If you are using a makefile, it could look like this:
|
|
|
|
*
|
|
|
|
* CFLAGS=`artsc-config --cflags`
|
|
|
|
* LDFLAGS=`artsc-config --libs`
|
|
|
|
*
|
|
|
|
* artscmt: artscmt.c
|
|
|
|
*/
|
|
|
|
#include <artsc.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
pthread_mutex_t arts_mutex; /* pthread mutex */
|
|
|
|
|
|
|
|
struct Writer
|
|
|
|
{
|
|
|
|
pthread_t thread;
|
|
|
|
arts_stream_t stream;
|
|
|
|
float freq;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define BUFFER_SIZE 1024
|
|
|
|
|
|
|
|
static void* writer(void *arg)
|
|
|
|
{
|
|
|
|
struct Writer *self = arg;
|
|
|
|
int pos = 0;
|
|
|
|
|
|
|
|
while(pos < 44100*10)
|
|
|
|
{
|
|
|
|
char buffer[BUFFER_SIZE], *to = buffer;
|
|
|
|
int i, written;
|
|
|
|
|
|
|
|
for(i=0;i<BUFFER_SIZE/4;i++)
|
|
|
|
{
|
|
|
|
/* generate two sin waves */
|
|
|
|
float fpos = ((float)pos)/44100.0;
|
|
|
|
long sample = (long)(sin(fpos*6.28*self->freq)*15000.0);
|
|
|
|
pos++;
|
|
|
|
|
|
|
|
/* put the samples in the packet */
|
|
|
|
*to++ = sample & 0xff;
|
|
|
|
*to++ = (sample >> 8) & 0xff;
|
|
|
|
*to++ = sample & 0xff;
|
|
|
|
*to++ = (sample >> 8) & 0xff;
|
|
|
|
}
|
|
|
|
|
|
|
|
written = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
int space;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since there is more than one thread, it is important not to keep the lock
|
|
|
|
* for a long time. We definitely don't want arts_write to block, while we
|
|
|
|
* keep the lock, to ensure that other threads can do something as well. So
|
|
|
|
* we check the available buffer space before writing to avoid blocking.
|
|
|
|
*/
|
|
|
|
pthread_mutex_lock(&arts_mutex);
|
|
|
|
space = arts_stream_get(self->stream, ARTS_P_BUFFER_SPACE);
|
|
|
|
if (space >= BUFFER_SIZE)
|
|
|
|
{
|
|
|
|
written = arts_write(self->stream, buffer, BUFFER_SIZE);
|
|
|
|
assert(written == BUFFER_SIZE); /* should handle errors here */
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&arts_mutex);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the buffer is full, wait some time to get free space again. The amout of
|
|
|
|
* time to wait needs to correspond to the buffer size we use for refilling.
|
|
|
|
*/
|
|
|
|
if (!written)
|
|
|
|
usleep(10000); /* 10ms */
|
|
|
|
} while(!written);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
struct Writer writer1, writer2;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = arts_init();
|
|
|
|
if(error < 0)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "error initializing aRts driver: %s\n", arts_error_text(error));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_init(&arts_mutex, 0);
|
|
|
|
|
|
|
|
writer1.stream = arts_play_stream(44100, 16, 2, "artscmt1");
|
|
|
|
writer1.freq = 440;
|
|
|
|
pthread_create(&writer1.thread, NULL, writer, &writer1);
|
|
|
|
|
|
|
|
writer2.stream = arts_play_stream(44100, 16, 2, "artscmt2");
|
|
|
|
writer2.freq = 880;
|
|
|
|
pthread_create(&writer2.thread, NULL, writer, &writer2);
|
|
|
|
|
|
|
|
pthread_join(writer1.thread, NULL);
|
|
|
|
pthread_join(writer2.thread, NULL);
|
|
|
|
|
|
|
|
arts_close_stream(writer1.stream);
|
|
|
|
arts_close_stream(writer2.stream);
|
|
|
|
|
|
|
|
pthread_mutex_destroy(&arts_mutex);
|
|
|
|
|
|
|
|
arts_free();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|