Browse Source

Remove JACK Ring Buffer from io-audio JACK Driver

The JACK ring buffer requires that a buffer be a power of two in size.
This is not possible if the number of voices is not a power of two, so
I have removed the JACK ring buffer from the io-audio JACK driver. I
have replaced it with use of the raw DMA buffer along with a current
fragment value to track where we should be reading from the DMA buffer.
pull/244/head
Shaun Tierney 10 years ago
parent
commit
4c889c5a67
1 changed files with 55 additions and 87 deletions
  1. +55
    -87
      qnx/ioaudio/ioaudio_driver.c

+ 55
- 87
qnx/ioaudio/ioaudio_driver.c View File

@@ -92,9 +92,19 @@ typedef struct jack_card
int voices;

/**
* Ringbuffer between io-audio and JACK
* DMA buffer between io-audio and JACK.
*/
jack_ringbuffer_t ringbuffer;
void * dmabuf;

/**
* Current DMA buffer fragment index between io-audio and JACK.
*/
int current_frag;

/**
* Number of DMA buffer fragments between io-audio and JACK.
*/
int num_frags;

/**
* Number of audio frames per fragment
@@ -250,21 +260,15 @@ int32_t cb_aquire(
}

/*
* Create shared memory region for ringbuffer
* Create shared memory region for DMA transfer
*/
config->dmabuf.addr = ado_shm_alloc( config->dmabuf.size,
config->dmabuf.name,
ADO_SHM_DMA_SAFE,
&config->dmabuf.phys_addr );

/*
* Set up JACK ringbuffer structure to use SHM region instead of own
* buffer.
*/
jack_card->ringbuffer.buf = (char*)config->dmabuf.addr;
jack_card->ringbuffer.size = config->dmabuf.size;
jack_card->ringbuffer.size_mask = config->dmabuf.size - 1;
jack_ringbuffer_reset( &jack_card->ringbuffer );
jack_card->dmabuf = config->dmabuf.addr;
jack_card->current_frag = 0;
jack_card->num_frags = config->mode.block.frags_total;

/*
* Store parameters for future use
@@ -292,8 +296,6 @@ int32_t cb_release(

jack_card->subchn.go = 0;

jack_ringbuffer_reset( &jack_card->ringbuffer );

ado_shm_free( pc->pcm_config->dmabuf.addr,
pc->pcm_config->dmabuf.size,
pc->pcm_config->dmabuf.name );
@@ -310,7 +312,11 @@ int32_t cb_prepare(
{
ado_debug( DB_LVL_DRIVER,
"deva-ctrl-jack: prepare()" );
jack_ringbuffer_reset( &jack_card->ringbuffer );

/* Reset the DMA buffer fragment index. */
pthread_mutex_lock( &jack_card->process_lock );
jack_card->current_frag = 0;
pthread_mutex_unlock( &jack_card->process_lock );
return EOK;
}

@@ -384,93 +390,55 @@ int jack_process(
int v;
jack_card_t* jack_card = (jack_card_t*)arg;

size_t total_size = nframes * sizeof(sample_t);
size_t size_completed;
size_t frame_size = nframes * sizeof(sample_t);
size_t frag_size = frame_size * jack_card->voices;

if( ( jack_card->fragsize != total_size ) )
if( jack_card->fragsize != frag_size )
{
ado_error(
"deva_ctrl-jack: mismatch of fragment size with number of frames requested" );
}

/*
* Try to lock the process mutex. If the lock can't be acquired, assume something is happening with the subchannel
* and write zeroes to JACK instead.
*/
if( jack_card->subchn.go
else if( jack_card->subchn.go
&& ( 0 == pthread_mutex_trylock( &jack_card->process_lock ) ) )
{
int voices = jack_card->subchn.pcm_config->format.voices;
size_t size_per_voice = total_size / voices;

void* jack_buf[voices];
for( v = 0; v < voices; ++v )
{
jack_buf[v] = jack_port_get_buffer( jack_card->ports[v],
nframes );
}
/* Get the current frame ( voice ) buffer */
char * frame_buf = (char * )jack_card->dmabuf;
frame_buf += jack_card->current_frag * frag_size;

for( size_completed = 0; size_completed < total_size; size_completed +=
size_per_voice )
for( v = 0; v < jack_card->voices; ++v )
{
for( v = 0; v < voices; ++v )
sample_t * jack_buf;
jack_buf = jack_port_get_buffer( jack_card->ports[v], nframes );
if( SND_PCM_SFMT_FLOAT_LE
== jack_card->subchn.pcm_config->format.format )
{
/*
* Advance ringbuffer write pointer on the assumption that io-audio has filled in nframes of data
*/
jack_ringbuffer_write_advance( &jack_card->ringbuffer,
size_per_voice );

jack_ringbuffer_data_t read_buf[2];
jack_ringbuffer_get_read_vector( &jack_card->ringbuffer,
read_buf );

if( SND_PCM_SFMT_FLOAT_LE
== jack_card->subchn.pcm_config->format.format )
{
jack_ringbuffer_read( &jack_card->ringbuffer,
jack_buf[v],
size_per_voice );
}
else if( SND_PCM_SFMT_S32_LE
== jack_card->subchn.pcm_config->format.format )
float * read_buf = ( float * )frame_buf;
memcpy( jack_buf, read_buf, frame_size );
}
else if( SND_PCM_SFMT_S32_LE
== jack_card->subchn.pcm_config->format.format )
{
int32_t * read_buf = ( int32_t * )frame_buf;
int s;
for( s = 0; s < nframes; ++s )
{
int s;
size_t remaining = size_per_voice / sizeof(sample_t);
read_buf[0].len /= sizeof(sample_t);
read_buf[1].len /= sizeof(sample_t);

int32_t* src = (sample_t*)read_buf[0].buf;
sample_t* dest = (sample_t*)jack_buf[v];
size_t amt = min( read_buf[0].len,
remaining );
for( s = 0; s < amt; ++s )
{
dest[s] = ( (sample_t)src[s] ) * ( (sample_t)1.0 )
/ ( (sample_t)INT_MAX );
}
remaining -= amt;
if( remaining > 0 )
{
src = (int32_t*)read_buf[1].buf;
dest += amt;
amt = min( read_buf[1].len,
remaining );
for( s = 0; s < amt; ++s )
{
dest[s] = ( (sample_t)src[s] ) * ( (sample_t)1.0 )
/ ( (sample_t)INT_MAX );
}
}
jack_ringbuffer_read_advance( &jack_card->ringbuffer,
size_per_voice );
}

jack_buf[v] += size_per_voice;
jack_buf[s] = ( (sample_t)read_buf[s] ) * ( (sample_t)1.0 )
/ ( (sample_t)INT_MAX );

}
}
dma_interrupt( jack_card->subchn.pcm_subchn );
frame_buf += frame_size;
}
++jack_card->current_frag;
if( jack_card->current_frag >= jack_card->num_frags )
{
jack_card->current_frag = 0;
}
dma_interrupt( jack_card->subchn.pcm_subchn );
pthread_mutex_unlock( &jack_card->process_lock );
}
else
@@ -485,7 +453,7 @@ int jack_process(
nframes );
memset( jack_buf,
0,
total_size );
frame_size );
}
}

@@ -643,14 +611,14 @@ int ctrl_init(
uint32_t rateflag = ado_pcm_rate2flag( rate );
jack_card->caps.rates = rateflag;

jack_card->caps.min_voices = 1;
jack_card->caps.min_voices = jack_card->voices;
jack_card->caps.max_voices = jack_card->voices;

/*
* Get size of ringbuffer from JACK server
*/
jack_card->fragsize = jack_get_buffer_size( jack_card->client )
* sizeof(sample_t);
* sizeof(sample_t) * jack_card->voices;
jack_card->caps.min_fragsize = jack_card->fragsize;
jack_card->caps.max_fragsize = jack_card->fragsize;
jack_card->caps.max_dma_size = 0;


Loading…
Cancel
Save