enable chosen single channel

This commit is contained in:
Baozhu Zuo 2017-09-30 16:00:07 +08:00
parent 6a0b216dbf
commit f362cdd383
1 changed files with 249 additions and 144 deletions

View File

@ -5,193 +5,291 @@
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
#include <alsa/pcm_external.h> #include <alsa/pcm_external.h>
#include <alsa/pcm_plugin.h> #include <alsa/pcm_plugin.h>
#include "ac108_help.h"
#include <math.h> #include <math.h>
#define ARRAY_SIZE(ary) (sizeof(ary)/sizeof(ary[0])) #define ARRAY_SIZE(ary) (sizeof(ary)/sizeof(ary[0]))
#define AC108_FRAME_SIZE 4096 #define AC108_FRAME_SIZE 4096
struct ac108_t { struct ac108_t {
snd_pcm_ioplug_t io; snd_pcm_ioplug_t io;
snd_pcm_t *slave; snd_pcm_t *pcm;
snd_pcm_hw_params_t *hw_params; snd_pcm_hw_params_t *hw_params;
unsigned int last_size; unsigned int last_size;
unsigned int ptr; unsigned int ptr;
void *buf;
unsigned int latency; // Delay in usec unsigned int latency; // Delay in usec
unsigned int bufferSize; // Size of sample buffer unsigned int bufferSize; // Size of sample buffer
}; };
static unsigned char capture_buf[AC108_FRAME_SIZE];
/* set up the fixed parameters of slave PCM hw_parmas */ /* set up the fixed parameters of pcm PCM hw_parmas */
static int ac108_slave_hw_params_half(struct ac108_t *rec, unsigned int rate,snd_pcm_format_t format) { static int ac108_slave_hw_params_half(struct ac108_t *capture, unsigned int rate,snd_pcm_format_t format) {
int err; int err;
snd_pcm_uframes_t bufferSize = rec->bufferSize; snd_pcm_uframes_t bufferSize = capture->bufferSize;
unsigned int latency = rec->latency; unsigned int latency = capture->latency;
unsigned int buffer_time = 0; unsigned int buffer_time = 0;
unsigned int period_time = 0; unsigned int period_time = 0;
if ((err = snd_pcm_hw_params_malloc(&rec->hw_params)) < 0) return err; if ((err = snd_pcm_hw_params_malloc(&capture->hw_params)) < 0) return err;
if ((err = snd_pcm_hw_params_any(rec->slave, rec->hw_params)) < 0) { if ((err = snd_pcm_hw_params_any(capture->pcm, capture->hw_params)) < 0) {
SNDERR("Cannot get slave hw_params"); SNDERR("Cannot get pcm hw_params");
goto out; goto out;
} }
if ((err = snd_pcm_hw_params_set_access(rec->slave, rec->hw_params, if ((err = snd_pcm_hw_params_set_access(capture->pcm, capture->hw_params,
SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
SNDERR("Cannot set slave access RW_INTERLEAVED"); SNDERR("Cannot set pcm access RW_INTERLEAVED");
goto out; goto out;
} }
if ((err = snd_pcm_hw_params_set_channels(rec->slave, rec->hw_params, 2)) < 0) { if ((err = snd_pcm_hw_params_set_channels(capture->pcm, capture->hw_params, 2)) < 0) {
SNDERR("Cannot set slave channels 2"); SNDERR("Cannot set pcm channels 2");
goto out; goto out;
} }
if ((err = snd_pcm_hw_params_set_format(rec->slave, rec->hw_params, if ((err = snd_pcm_hw_params_set_format(capture->pcm, capture->hw_params,
format)) < 0) { format)) < 0) {
SNDERR("Cannot set slave format"); SNDERR("Cannot set pcm format");
goto out; goto out;
} }
if ((err = snd_pcm_hw_params_set_rate(rec->slave, rec->hw_params, rate, 0)) < 0) { if ((err = snd_pcm_hw_params_set_rate(capture->pcm, capture->hw_params, rate, 0)) < 0) {
SNDERR("Cannot set slave rate %d", rate); SNDERR("Cannot set pcm rate %d", rate);
goto out; goto out;
} }
err = snd_pcm_hw_params_get_buffer_time_max(rec->hw_params, err = snd_pcm_hw_params_get_buffer_time_max(capture->hw_params,
&buffer_time, 0); &buffer_time, 0);
if (buffer_time > 80000) if (buffer_time > 80000)
buffer_time = 80000; buffer_time = 80000;
period_time = buffer_time / 4; period_time = buffer_time / 4;
err = snd_pcm_hw_params_set_period_time_near(rec->slave, rec->hw_params, err = snd_pcm_hw_params_set_period_time_near(capture->pcm, capture->hw_params,
&period_time, 0); &period_time, 0);
if (err < 0) { if (err < 0) {
fprintf(stderr,"Unable to set_period_time_near"); fprintf(stderr,"Unable to set_period_time_near");
goto out; goto out;
} }
err = snd_pcm_hw_params_set_buffer_time_near(rec->slave, rec->hw_params, err = snd_pcm_hw_params_set_buffer_time_near(capture->pcm, capture->hw_params,
&buffer_time, 0); &buffer_time, 0);
if (err < 0) { if (err < 0) {
fprintf(stderr,"Unable to set_buffer_time_near"); fprintf(stderr,"Unable to set_buffer_time_near");
goto out; goto out;
} }
rec->bufferSize = bufferSize; capture->bufferSize = bufferSize;
rec->latency = latency; capture->latency = latency;
return 0; return 0;
out: out:
free(rec->hw_params); free(capture->hw_params);
rec->hw_params = NULL; capture->hw_params = NULL;
return err; return err;
} }
/* /*
* start and stop callbacks - just trigger slave PCM * start and stop callbacks - just trigger pcm PCM
*/ */
static int ac108_start(snd_pcm_ioplug_t *io) { static int ac108_start(snd_pcm_ioplug_t *io) {
struct ac108_t *rec = io->private_data; struct ac108_t *capture = io->private_data;
fprintf(stderr,"ac108_start: %d\n",io->buffer_size);
if(!rec->slave) { if(!capture->pcm) {
fprintf(stderr, "slave is lost\n"); fprintf(stderr, "pcm is lost\n");
} }
return snd_pcm_start(rec->slave); return snd_pcm_start(capture->pcm);
} }
static int ac108_stop(snd_pcm_ioplug_t *io) { static int ac108_stop(snd_pcm_ioplug_t *io) {
struct ac108_t *rec = io->private_data; struct ac108_t *capture = io->private_data;
fprintf(stderr,"ac108_stop!\n");
return snd_pcm_drop(rec->slave); return snd_pcm_drop(capture->pcm);
} }
/* /*
* pointer callback * pointer callback
* *
* Calculate the current position from the delay of slave PCM * Calculate the current position from the delay of pcm PCM
*/ */
static snd_pcm_sframes_t ac108_pointer(snd_pcm_ioplug_t *io) { static snd_pcm_sframes_t ac108_pointer(snd_pcm_ioplug_t *io) {
struct ac108_t *rec = io->private_data;
struct ac108_t *capture = io->private_data;
int bps = snd_pcm_format_width(io->format) / 8;
int err, size; int err, size;
assert(rec); assert(capture);
size = snd_pcm_avail(rec->slave); size = snd_pcm_avail(capture->pcm);
if (size < 0) return size; if (size < 0)
size = size /2; return size;
if (size > rec->last_size) {
rec->ptr += size - rec->last_size; size = size/2;
rec->ptr %= io->buffer_size;
if (size > capture->last_size) {
capture->ptr += size - capture->last_size;
capture->ptr %= io->buffer_size;
} }
rec->last_size = size; //fprintf(stderr, "%s :%d %d %d %d %d %d\n", __func__,capture->ptr ,capture->last_size,size, io->buffer_size,io->appl_ptr, io->hw_ptr);
capture->last_size = size;
//fprintf(stderr, "%s :%d %d %d %d\n", __func__, rec->ptr,size, io->appl_ptr, io->hw_ptr); return capture->ptr;
return rec->ptr;
} }
/* /*
* transfer callback * transfer callback
*/ */
static snd_pcm_sframes_t ac108_transfer(snd_pcm_ioplug_t *io, static snd_pcm_sframes_t ac108_transfer(snd_pcm_ioplug_t *io,
const snd_pcm_channel_area_t *areas, const snd_pcm_channel_area_t *dst_areas,
snd_pcm_uframes_t offset, snd_pcm_uframes_t dst_offset,
snd_pcm_uframes_t size) { snd_pcm_uframes_t size) {
struct ac108_t *rec = io->private_data; struct ac108_t *capture = io->private_data;
char *buf; int chn;
ssize_t result; unsigned char *dst_samples[io->channels];
int err; int dst_steps[io->channels];
int bps = snd_pcm_format_width(io->format) / 8; /* bytes per sample */
//int phys_bps = snd_pcm_format_physical_width(capture->format) / 8;
//int big_endian = snd_pcm_format_big_endian(capture->format) == 1;
//int to_unsigned = snd_pcm_format_unsigned(capture->format) == 1;
//int is_float = (capture->format == SND_PCM_FORMAT_FLOAT_LE ||capture->format == SND_PCM_FORMAT_FLOAT_BE);
int i;
int count = 0;
int err = 0;
unsigned char *src_buf;
unsigned char *src_data[4][4];
memset(capture_buf,0,AC108_FRAME_SIZE);
if(snd_pcm_avail(capture->pcm) > size*2){
if ((err = snd_pcm_readi (capture->pcm, capture_buf, size*2)) != size*2) {
fprintf (stderr, "read from audio interface failed %d %d %s!\n",size,err,snd_strerror (err));
exit(EXIT_FAILURE);
size = 0 ;
}
}else{
size = 0;
}
#if 1
/* verify and prepare the contents of areas */
for (chn = 0; chn < io->channels; chn++) {
if ((dst_areas[chn].first % 8) != 0) {
fprintf(stderr,"dst_areas[%i].first == %i, aborting...\n", chn, dst_areas[chn].first);
exit(EXIT_FAILURE);
}
dst_samples[chn] = /*(signed short *)*/(((unsigned char *)dst_areas[chn].addr) + (dst_areas[chn].first / 8));
if ((dst_areas[chn].step % 16) != 0) {
fprintf(stderr,"dst_areas[%i].step == %i, aborting...\n", chn, dst_areas[chn].step);
exit(EXIT_FAILURE);
}
dst_steps[chn] = dst_areas[chn].step / 8;
dst_samples[chn] += dst_offset * dst_steps[chn];
}
#endif
//fprintf(stderr,"ac108_transfer: %d %d %d %d\n", size,dst_offset,io->channels,bps);
// for(i = 0; i < size*2*bps;i++){
// fprintf(stderr,"%x ",capture_buf[i]);
// if(i%4 == 0)
// fprintf(stderr,"\n");
// }
//generate_sine(dst_areas, dst_offset,size, &count);
src_buf = capture_buf;
// while(1){
// if(src_buf[0] == 0 && src_buf[0 + bps] == 1 &&
// src_buf[0 + 2*bps] == 2 && src_buf[0 + 3*bps] == 3)
// break;
// else
// src_buf += 4*bps;
// }
#if 1
while(count < size){
for(chn = 0; chn < 4; chn++){
for (i = 0; i < bps; i++){
src_data[chn][i] = src_buf[i];
}
src_buf += bps ;
}
for(chn = 0; chn < io->channels; chn++){
for (i = 0; i < bps; i++){
*(dst_samples[chn] + i) = src_data[chn][i];
//fprintf(stderr,"%x ",*(dst_samples[chn] + i));
}
//fprintf(stderr,"%x %x %x %x\n",src_buf[3],src_buf[2],src_buf[1],src_buf[0]);
//fprintf(stderr,"\n");
dst_samples[chn] += dst_steps[chn];
}
count++;
}
#endif
capture->last_size -= size;
#if 0
/* we handle only an interleaved buffer */ /* we handle only an interleaved buffer */
buf = (char *)areas->addr + (areas->first + areas->step * offset) / 8; dst_buf = (char *)areas->addr + (areas->first + areas->step * offset) / 8;
result = snd_pcm_readi(rec->slave, buf, size*2); buf = dst_buf;
snd_pcm_readi(capture->pcm, capture_buf, size/2);
#if 1
for(a = 0; a < size*2;a++){
fprintf(stderr,"%x ",capture_buf[a]);
if(a%4 == 0)
fprintf(stderr,"\n");
}
#endif
memcpy((char*)dst_buf,capture_buf,size/2);
fprintf(stderr,"ac108_transfer: %d %d %d \n", size,offset,io->channels);
if (result <= 0) { if (result <= 0) {
fprintf(stderr, "%s out error:%d %d\n", __func__, result); fprintf(stderr, "%s out error:%d %d\n", __func__, result);
return result; return result;
} }
rec->last_size -= size; capture->last_size -= size;
#endif
return size; return size;
} }
/* /*
* poll-related callbacks - just pass to slave PCM * poll-related callbacks - just pass to pcm PCM
*/ */
static int ac108_poll_descriptors_count(snd_pcm_ioplug_t *io) { static int ac108_poll_descriptors_count(snd_pcm_ioplug_t *io) {
struct ac108_t *rec = io->private_data; struct ac108_t *capture = io->private_data;
//fprintf(stderr, "%s\n", __FUNCTION__); //fprintf(stderr, "%s\n", __FUNCTION__);
return snd_pcm_poll_descriptors_count(rec->slave); return snd_pcm_poll_descriptors_count(capture->pcm);
} }
static int ac108_poll_descriptors(snd_pcm_ioplug_t *io, struct pollfd *pfd, static int ac108_poll_descriptors(snd_pcm_ioplug_t *io, struct pollfd *pfd,
unsigned int space) { unsigned int space) {
struct ac108_t *rec = io->private_data; struct ac108_t *capture = io->private_data;
//fprintf(stderr, "%s\n", __FUNCTION__); //fprintf(stderr, "%s\n", __FUNCTION__);
return snd_pcm_poll_descriptors(rec->slave, pfd, space); return snd_pcm_poll_descriptors(capture->pcm, pfd, space);
} }
static int ac108_poll_revents(snd_pcm_ioplug_t *io, struct pollfd *pfd, static int ac108_poll_revents(snd_pcm_ioplug_t *io, struct pollfd *pfd,
unsigned int nfds, unsigned short *revents) { unsigned int nfds, unsigned short *revents) {
struct ac108_t *rec = io->private_data; struct ac108_t *capture = io->private_data;
//fprintf(stderr, "%s\n", __FUNCTION__); //fprintf(stderr, "%s\n", __FUNCTION__);
return snd_pcm_poll_descriptors_revents(rec->slave, pfd, nfds, revents); return snd_pcm_poll_descriptors_revents(capture->pcm, pfd, nfds, revents);
} }
/* /*
* close callback * close callback
*/ */
static int ac108_close(snd_pcm_ioplug_t *io) { static int ac108_close(snd_pcm_ioplug_t *io) {
struct ac108_t *rec = io->private_data; struct ac108_t *capture = io->private_data;
fprintf(stderr,"ac108_close\n");
if (capture->pcm)
snd_pcm_close(capture->pcm);
if (rec->slave) return snd_pcm_close(rec->slave);
return 0; return 0;
} }
static int setSoftwareParams(struct ac108_t *rec) { static int setSoftwareParams(struct ac108_t *capture) {
snd_pcm_sw_params_t *softwareParams; snd_pcm_sw_params_t *softwareParams;
int err; int err;
@ -201,21 +299,21 @@ static int setSoftwareParams(struct ac108_t *rec) {
snd_pcm_sw_params_alloca(&softwareParams); snd_pcm_sw_params_alloca(&softwareParams);
// Get the current software parameters // Get the current software parameters
err = snd_pcm_sw_params_current(rec->slave, softwareParams); err = snd_pcm_sw_params_current(capture->pcm, softwareParams);
if (err < 0) { if (err < 0) {
fprintf(stderr, "Unable to get software parameters: %s", snd_strerror(err)); fprintf(stderr, "Unable to get software parameters: %s", snd_strerror(err));
goto done; goto done;
} }
// Configure ALSA to start the transfer when the buffer is almost full. // Configure ALSA to start the transfer when the buffer is almost full.
snd_pcm_get_params(rec->slave, &bufferSize, &periodSize); snd_pcm_get_params(capture->pcm, &bufferSize, &periodSize);
startThreshold = 1; startThreshold = 1;
stopThreshold = bufferSize; stopThreshold = bufferSize;
err = snd_pcm_sw_params_set_start_threshold(rec->slave, softwareParams, err = snd_pcm_sw_params_set_start_threshold(capture->pcm, softwareParams,
startThreshold); startThreshold);
if (err < 0) { if (err < 0) {
fprintf(stderr, "Unable to set start threshold to %lu frames: %s", fprintf(stderr, "Unable to set start threshold to %lu frames: %s",
@ -223,7 +321,7 @@ static int setSoftwareParams(struct ac108_t *rec) {
goto done; goto done;
} }
err = snd_pcm_sw_params_set_stop_threshold(rec->slave, softwareParams, err = snd_pcm_sw_params_set_stop_threshold(capture->pcm, softwareParams,
stopThreshold); stopThreshold);
if (err < 0) { if (err < 0) {
fprintf(stderr, "Unable to set stop threshold to %lu frames: %s", fprintf(stderr, "Unable to set stop threshold to %lu frames: %s",
@ -232,7 +330,7 @@ static int setSoftwareParams(struct ac108_t *rec) {
} }
// Allow the transfer to start when at least periodSize samples can be // Allow the transfer to start when at least periodSize samples can be
// processed. // processed.
err = snd_pcm_sw_params_set_avail_min(rec->slave, softwareParams, err = snd_pcm_sw_params_set_avail_min(capture->pcm, softwareParams,
periodSize); periodSize);
if (err < 0) { if (err < 0) {
fprintf(stderr, "Unable to configure available minimum to %lu: %s", fprintf(stderr, "Unable to configure available minimum to %lu: %s",
@ -241,7 +339,7 @@ static int setSoftwareParams(struct ac108_t *rec) {
} }
// Commit the software parameters back to the device. // Commit the software parameters back to the device.
err = snd_pcm_sw_params(rec->slave, softwareParams); err = snd_pcm_sw_params(capture->pcm, softwareParams);
if (err < 0) fprintf(stderr, "Unable to configure software parameters: %s", if (err < 0) fprintf(stderr, "Unable to configure software parameters: %s",
snd_strerror(err)); snd_strerror(err));
@ -256,77 +354,71 @@ done:
/* /*
* hw_params callback * hw_params callback
* *
* Set up slave PCM according to the current parameters * Set up pcm PCM according to the current parameters
*/ */
//static int ac108_hw_params(snd_pcm_ioplug_t *io, //static int ac108_hw_params(snd_pcm_ioplug_t *io,
// snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED) { // snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED) {
static int ac108_hw_params(snd_pcm_ioplug_t *io) { static int ac108_hw_params(snd_pcm_ioplug_t *io) {
struct ac108_t *rec = io->private_data; struct ac108_t *capture = io->private_data;
snd_pcm_sw_params_t *sparams; snd_pcm_sw_params_t *sparams;
snd_pcm_uframes_t period_size; snd_pcm_uframes_t period_size;
snd_pcm_uframes_t buffer_size; snd_pcm_uframes_t buffer_size;
int err; int err;
if (!rec->hw_params) { if (!capture->hw_params) {
err = ac108_slave_hw_params_half(rec, 2*io->rate,io->format); err = ac108_slave_hw_params_half(capture, 2*io->rate,io->format);
if (err < 0) { if (err < 0) {
fprintf(stderr, "ac108_slave_hw_params_half error\n"); fprintf(stderr, "ac108_slave_hw_params_half error\n");
return err; return err;
} }
} }
period_size = io->period_size; period_size = io->period_size;
if ((err = snd_pcm_hw_params_set_period_size_near(rec->slave, rec->hw_params, if ((err = snd_pcm_hw_params_set_period_size_near(capture->pcm, capture->hw_params,
&period_size, NULL)) < 0) { &period_size, NULL)) < 0) {
SNDERR("Cannot set slave period size %ld", period_size); SNDERR("Cannot set pcm period size %ld", period_size);
return err; return err;
} }
buffer_size = io->buffer_size; buffer_size = io->buffer_size;
if ((err = snd_pcm_hw_params_set_buffer_size_near(rec->slave, rec->hw_params, if ((err = snd_pcm_hw_params_set_buffer_size_near(capture->pcm, capture->hw_params,
&buffer_size)) < 0) { &buffer_size)) < 0) {
SNDERR("Cannot set slave buffer size %ld", buffer_size); SNDERR("Cannot set pcm buffer size %ld", buffer_size);
return err; return err;
} }
if ((err = snd_pcm_hw_params(rec->slave, rec->hw_params)) < 0) { if ((err = snd_pcm_hw_params(capture->pcm, capture->hw_params)) < 0) {
SNDERR("Cannot set slave hw_params"); SNDERR("Cannot set pcm hw_params");
return err; return err;
} }
setSoftwareParams(capture);
setSoftwareParams(rec); fprintf(stderr, "ac108_hw_params\n");
return 0; return 0;
} }
/* /*
* hw_free callback * hw_free callback
*/ */
static int ac108_hw_free(snd_pcm_ioplug_t *io) { static int ac108_hw_free(snd_pcm_ioplug_t *io) {
struct ac108_t *rec = io->private_data; struct ac108_t *capture = io->private_data;
free(rec->hw_params); free(capture->hw_params);
if (rec->buf != NULL) { capture->hw_params = NULL;
free(rec->buf); fprintf(stderr,"ac108_hw_free\n");
rec->buf = NULL;
}
rec->hw_params = NULL;
return snd_pcm_hw_free(rec->slave); return snd_pcm_hw_free(capture->pcm);
} }
static int ac108_prepare(snd_pcm_ioplug_t *io) { static int ac108_prepare(snd_pcm_ioplug_t *io) {
struct ac108_t *rec = io->private_data; struct ac108_t *capture = io->private_data;
rec->ptr = 0; capture->ptr = 0;
rec->last_size =0; capture->last_size =0;
if (rec->buf == NULL) { fprintf(stderr,"ac108_prepare\n");
rec->buf = malloc(io->buffer_size); return snd_pcm_prepare(capture->pcm);
}
return snd_pcm_prepare(rec->slave);
} }
static int ac108_drain(snd_pcm_ioplug_t *io) { static int ac108_drain(snd_pcm_ioplug_t *io) {
struct ac108_t *rec = io->private_data; struct ac108_t *capture = io->private_data;
return snd_pcm_drain(rec->slave);
return snd_pcm_drain(capture->pcm);
} }
static int ac108_sw_params(snd_pcm_ioplug_t *io, snd_pcm_sw_params_t *params) { static int ac108_sw_params(snd_pcm_ioplug_t *io, snd_pcm_sw_params_t *params) {
struct ac108_t *rec = io->private_data; struct ac108_t *capture = io->private_data;
return 0; return 0;
} }
@ -356,10 +448,9 @@ static snd_pcm_ioplug_callback_t a108_ops = {
}; };
static int ac108_set_hw_constraint(struct ac108_t *rec) { static int ac108_set_hw_constraint(struct ac108_t *capture) {
static unsigned int accesses[] = { static unsigned int accesses[] = {
SND_PCM_ACCESS_RW_INTERLEAVED, SND_PCM_ACCESS_RW_INTERLEAVED
SND_PCM_ACCESS_RW_NONINTERLEAVED
}; };
unsigned int formats[] = { SND_PCM_FORMAT_S32, unsigned int formats[] = { SND_PCM_FORMAT_S32,
SND_PCM_FORMAT_S16 }; SND_PCM_FORMAT_S16 };
@ -374,30 +465,43 @@ static int ac108_set_hw_constraint(struct ac108_t *rec) {
unsigned int period_bytes, max_periods; unsigned int period_bytes, max_periods;
err = snd_pcm_ioplug_set_param_list(&rec->io, err = snd_pcm_ioplug_set_param_list(&capture->io,
SND_PCM_IOPLUG_HW_ACCESS, SND_PCM_IOPLUG_HW_ACCESS,
ARRAY_SIZE(accesses), ARRAY_SIZE(accesses),
accesses); accesses);
if (err < 0) return err; if (err < 0){
SNDERR("ioplug cannot set ac108 hw access");
return err;
}
if ((err = snd_pcm_ioplug_set_param_list(&rec->io, SND_PCM_IOPLUG_HW_FORMAT, if ((err = snd_pcm_ioplug_set_param_list(&capture->io, SND_PCM_IOPLUG_HW_FORMAT,
ARRAY_SIZE(formats), formats)) < 0 || ARRAY_SIZE(formats), formats)) < 0 ||
(err = snd_pcm_ioplug_set_param_minmax(&rec->io, SND_PCM_IOPLUG_HW_CHANNELS, (err = snd_pcm_ioplug_set_param_minmax(&capture->io, SND_PCM_IOPLUG_HW_CHANNELS,
4, 4)) < 0 || 1, 4)) < 0 ||
(err = snd_pcm_ioplug_set_param_list(&rec->io, SND_PCM_IOPLUG_HW_RATE, (err = snd_pcm_ioplug_set_param_list(&capture->io, SND_PCM_IOPLUG_HW_RATE,
ARRAY_SIZE(rates), rates)) < 0) return err; ARRAY_SIZE(rates), rates)) < 0) {
err = snd_pcm_ioplug_set_param_minmax(&rec->io, SNDERR("ioplug cannot set ac108 format channel rate!");
SND_PCM_IOPLUG_HW_BUFFER_BYTES, return err;
}
err = snd_pcm_ioplug_set_param_minmax(&capture->io,SND_PCM_IOPLUG_HW_BUFFER_BYTES,
1, 4 * 1024 * 1024); 1, 4 * 1024 * 1024);
if (err < 0) return err; if (err < 0){
SNDERR("ioplug cannot set ac108 hw buffer bytes");
return err;
}
err = snd_pcm_ioplug_set_param_minmax(&rec->io, err = snd_pcm_ioplug_set_param_minmax(&capture->io,SND_PCM_IOPLUG_HW_PERIOD_BYTES,
SND_PCM_IOPLUG_HW_PERIOD_BYTES,
128, 2 * 1024 * 1024); 128, 2 * 1024 * 1024);
if (err < 0) return err; if (err < 0) {
SNDERR("ioplug cannot set ac108 hw period bytes");
return err;
}
err = snd_pcm_ioplug_set_param_minmax(&rec->io, SND_PCM_IOPLUG_HW_PERIODS, err = snd_pcm_ioplug_set_param_minmax(&capture->io, SND_PCM_IOPLUG_HW_PERIODS,3, 1024);
3, 1024); if (err < 0) {
SNDERR("ioplug cannot set ac108 hw periods");
return err;
}
return 0; return 0;
} }
@ -412,7 +516,7 @@ SND_PCM_PLUGIN_DEFINE_FUNC(ac108) {
const char *pcm_string = NULL; const char *pcm_string = NULL;
snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE; snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE;
char devstr[128], tmpcard[8]; char devstr[128], tmpcard[8];
struct ac108_t *rec; struct ac108_t *capture;
int channels; int channels;
struct pollfd fds; struct pollfd fds;
if (stream != SND_PCM_STREAM_CAPTURE) { if (stream != SND_PCM_STREAM_CAPTURE) {
@ -449,36 +553,37 @@ SND_PCM_PLUGIN_DEFINE_FUNC(ac108) {
} }
} }
rec = calloc(1, sizeof(*rec));
if (!rec) { capture = calloc(1, sizeof(*capture));
if (!capture) {
SNDERR("cannot allocate"); SNDERR("cannot allocate");
return -ENOMEM; return -ENOMEM;
} }
err = snd_pcm_open(&rec->slave, pcm_string, stream, mode); err = snd_pcm_open(&capture->pcm, pcm_string, stream, mode);
if (err < 0) goto error; if (err < 0) goto error;
//SND_PCM_NONBLOCK //SND_PCM_NONBLOCK
rec->io.version = SND_PCM_IOPLUG_VERSION; capture->io.version = SND_PCM_IOPLUG_VERSION;
rec->io.name = "AC108 decode Plugin"; capture->io.name = "AC108 decode Plugin";
rec->io.mmap_rw = 0; capture->io.mmap_rw = 0;
rec->io.callback = &a108_ops; capture->io.callback = &a108_ops;
rec->io.private_data = rec; capture->io.private_data = capture;
err = snd_pcm_ioplug_create(&rec->io, name, stream, mode); err = snd_pcm_ioplug_create(&capture->io, name, stream, mode);
if (err < 0) goto error; if (err < 0) goto error;
if ((err = ac108_set_hw_constraint(rec)) < 0) { if ((err = ac108_set_hw_constraint(capture)) < 0) {
snd_pcm_ioplug_delete(&rec->io); snd_pcm_ioplug_delete(&capture->io);
return err; return err;
} }
*pcmp = rec->io.pcm; *pcmp = capture->io.pcm;
return 0; return 0;
error: error:
if (rec->slave) snd_pcm_close(rec->slave); if (capture->pcm) snd_pcm_close(capture->pcm);
free(rec); free(capture);
return err; return err;
} }