Merge branch 'caed_playback_tuning' of https://github.com/tryphon/rivendell into tryphon-caed_playback_tuning

This commit is contained in:
Fred Gleason 2018-05-30 20:14:26 +00:00
commit 6d7ed78c62

View File

@ -284,249 +284,260 @@ void AlsaPlay2Callback(struct alsa_format *alsa_format)
memset(alsa_format->card_buffer,0,alsa_format->card_buffer_size); memset(alsa_format->card_buffer,0,alsa_format->card_buffer_size);
switch(alsa_format->format) { switch(alsa_format->format) {
case SND_PCM_FORMAT_S16_LE: case SND_PCM_FORMAT_S16_LE:
for(unsigned j=0;j<RD_MAX_STREAMS;j++) { for(unsigned j=0;j<RD_MAX_STREAMS;j++) {
if(alsa_playing[alsa_format->card][j]) { if(alsa_playing[alsa_format->card][j]) {
switch(alsa_output_channels[alsa_format->card][j]) { switch(alsa_output_channels[alsa_format->card][j]) {
case 1: case 1:
n=alsa_play_ring[alsa_format->card][j]-> n=alsa_play_ring[alsa_format->card][j]->
read(alsa_buffer,alsa_format-> read(alsa_buffer,alsa_format->
buffer_size/alsa_format->periods)/ buffer_size/alsa_format->periods)/
(2*sizeof(int16_t)); (2*sizeof(int16_t));
stream_out_meter=0; // Stream Output Meters stream_out_meter=0; // Stream Output Meters
for(int k=0;k<n;k++) { for(int k=0;k<n;k++) {
if(abs(((int16_t *)alsa_buffer)[k])>stream_out_meter) { if(abs(((int16_t *)alsa_buffer)[k])>stream_out_meter) {
stream_out_meter=abs(((int16_t *)alsa_buffer)[k]); stream_out_meter=abs(((int16_t *)alsa_buffer)[k]);
} }
} }
alsa_stream_output_meter[alsa_format->card][j][0]-> alsa_stream_output_meter[alsa_format->card][j][0]->
addValue(((double)stream_out_meter)/32768.0); addValue(((double)stream_out_meter)/32768.0);
alsa_stream_output_meter[alsa_format->card][j][1]-> alsa_stream_output_meter[alsa_format->card][j][1]->
addValue(((double)stream_out_meter)/32768.0); addValue(((double)stream_out_meter)/32768.0);
modulo=alsa_format->channels; modulo=alsa_format->channels;
for(unsigned i=0;i<(alsa_format->channels/2);i++) { for(unsigned i=0;i<(alsa_format->channels/2);i++) {
if(alsa_output_volume[alsa_format->card][i][j]!=0.0) { if(alsa_output_volume[alsa_format->card][i][j]!=0.0) {
for(int k=0;k<(2*n);k++) { for(int k=0;k<(2*n);k++) {
((int16_t *)alsa_format->card_buffer)[modulo*k+2*i]+= ((int16_t *)alsa_format->card_buffer)[modulo*k+2*i]+=
(int16_t)(alsa_output_volume[alsa_format->card][i][j]* (int16_t)(alsa_output_volume[alsa_format->card][i][j]*
(double)(((int16_t *)alsa_buffer)[k])); (double)(((int16_t *)alsa_buffer)[k]));
((int16_t *)alsa_format->card_buffer)[modulo*k+2*i+1]+= ((int16_t *)alsa_format->card_buffer)[modulo*k+2*i+1]+=
(int16_t)(alsa_output_volume[alsa_format->card][i][j]* (int16_t)(alsa_output_volume[alsa_format->card][i][j]*
(double)(((int16_t *)alsa_buffer)[k])); (double)(((int16_t *)alsa_buffer)[k]));
} }
} }
} }
n*=2; n*=2;
break; break;
case 2: case 2:
n=alsa_play_ring[alsa_format->card][j]-> n=alsa_play_ring[alsa_format->card][j]->
read(alsa_buffer,alsa_format->buffer_size*2/ read(alsa_buffer,alsa_format->buffer_size*2/
alsa_format->periods)/(2*sizeof(int16_t)); alsa_format->periods)/(2*sizeof(int16_t));
for(unsigned k=0;k<2;k++) { // Stream Output Meters for(unsigned k=0;k<2;k++) { // Stream Output Meters
stream_out_meter=0; stream_out_meter=0;
for(int l=0;l<n;l+=2) { for(int l=0;l<n;l+=2) {
if(abs(((int16_t *)alsa_buffer)[l+k])>stream_out_meter) { if(abs(((int16_t *)alsa_buffer)[l+k])>stream_out_meter) {
stream_out_meter=abs(((int16_t *)alsa_buffer)[l+k]); stream_out_meter=abs(((int16_t *)alsa_buffer)[l+k]);
} }
} }
alsa_stream_output_meter[alsa_format->card][j][k]-> alsa_stream_output_meter[alsa_format->card][j][k]->
addValue(((double)stream_out_meter)/32768.0); addValue(((double)stream_out_meter)/32768.0);
} }
modulo=alsa_format->channels; modulo=alsa_format->channels;
for(unsigned i=0;i<(alsa_format->channels/2);i++) { for(unsigned i=0;i<(alsa_format->channels/2);i++) {
if(alsa_output_volume[alsa_format->card][i][j]!=0.0) { if(alsa_output_volume[alsa_format->card][i][j]!=0.0) {
for(int k=0;k<n;k++) { for(int k=0;k<n;k++) {
((int16_t *)alsa_format->card_buffer)[modulo*k+2*i]+= ((int16_t *)alsa_format->card_buffer)[modulo*k+2*i]+=
(int16_t)(alsa_output_volume[alsa_format->card][i][j]* (int16_t)(alsa_output_volume[alsa_format->card][i][j]*
(double)(((int16_t *)alsa_buffer)[2*k])); (double)(((int16_t *)alsa_buffer)[2*k]));
((int16_t *)alsa_format->card_buffer)[modulo*k+2*i+1]+= ((int16_t *)alsa_format->card_buffer)[modulo*k+2*i+1]+=
(int16_t)(alsa_output_volume[alsa_format->card][i][j]* (int16_t)(alsa_output_volume[alsa_format->card][i][j]*
(double)(((int16_t *)alsa_buffer)[2*k+1])); (double)(((int16_t *)alsa_buffer)[2*k+1]));
} }
} }
} }
break; break;
} }
alsa_output_pos[alsa_format->card][j]+=n; alsa_output_pos[alsa_format->card][j]+=n;
if((n==0)&&alsa_eof[alsa_format->card][j]) { if((n==0)&&alsa_eof[alsa_format->card][j]) {
alsa_stopping[alsa_format->card][j]=true; alsa_stopping[alsa_format->card][j]=true;
} }
} }
} }
n=alsa_format->buffer_size/(2*alsa_format->periods); n=alsa_format->buffer_size/(2*alsa_format->periods);
// //
// Process Passthroughs // Process Passthroughs
// //
for(unsigned i=0;i<alsa_format->capture_channels;i+=2) { for(unsigned i=0;i<alsa_format->capture_channels;i+=2) {
p=alsa_passthrough_ring[alsa_format->card][i/2]-> p=alsa_passthrough_ring[alsa_format->card][i/2]->
read(alsa_format->passthrough_buffer,4*n)/4; read(alsa_format->passthrough_buffer,4*n)/4;
for(unsigned j=0;j<alsa_format->channels;j+=2) { bool zero_volume = true;
for(unsigned k=0;k<2;k++) { for (unsigned j=0;j<alsa_format->channels && zero_volume;j+=1) {
for(int l=0;l<p;l++) { zero_volume = (alsa_passthrough_volume[alsa_format->card][i/2][j] == 0.0);
((int16_t *)alsa_format-> }
card_buffer)[alsa_format->channels*l+j+k]+= if (!zero_volume) {
(int16_t)((double)((int16_t *) for(unsigned j=0;j<alsa_format->channels;j+=2) {
alsa_format->passthrough_buffer)[2*l+k]* double passthrough_volume = alsa_passthrough_volume[alsa_format->card][i/2][j/2];
alsa_passthrough_volume[alsa_format->card][i/2][j/2]); if (passthrough_volume != 0.0) {
} for(unsigned k=0;k<2;k++) {
} for(int l=0;l<p;l++) {
} ((int16_t *)alsa_format->
} card_buffer)[alsa_format->channels*l+j+k]+=
(int16_t)((double)((int16_t *)alsa_format->passthrough_buffer)[2*l+k]*passthrough_volume);
}
}
}
}
}
}
// //
// Process Output Meters // Process Output Meters
// //
for(unsigned i=0;i<alsa_format->channels;i+=2) { for(unsigned i=0;i<alsa_format->channels;i+=2) {
unsigned port=i/2; unsigned port=i/2;
for(unsigned j=0;j<2;j++) { for(unsigned j=0;j<2;j++) {
out_meter[port][j]=0; out_meter[port][j]=0;
for(unsigned k=0;k<alsa_format->buffer_size;k++) { for(unsigned k=0;k<alsa_format->buffer_size;k++) {
if(((int16_t *)alsa_format-> int16_t sample = ((int16_t *)alsa_format->
card_buffer)[alsa_format->channels*k+2*i+j]> card_buffer)[alsa_format->channels*k+2*i+j];
out_meter[i][j]) {
out_meter[i][j]=
((int16_t *)alsa_format->
card_buffer)[alsa_format->channels*k+2*i+j];
}
}
alsa_output_meter[alsa_format->card][i][j]->
addValue(((double)out_meter[i][j])/32768.0);
}
}
break;
case SND_PCM_FORMAT_S32_LE: if(sample> out_meter[i][j]) {
for(unsigned j=0;j<RD_MAX_STREAMS;j++) { out_meter[i][j]= sample;
if(alsa_playing[alsa_format->card][j]) { }
switch(alsa_output_channels[alsa_format->card][j]) { }
case 1: alsa_output_meter[alsa_format->card][i][j]->
n=alsa_play_ring[alsa_format->card][j]-> addValue(((double)out_meter[i][j])/32768.0);
read(alsa_buffer,alsa_format->buffer_size/ }
alsa_format->periods)/(2*sizeof(int16_t)); }
stream_out_meter=0; break;
for(int k=0;k<n;k++) { // Stream Output Meters
if(abs(((int16_t *)alsa_buffer)[k])>stream_out_meter) {
stream_out_meter=abs(((int16_t *)alsa_buffer)[k]);
}
}
alsa_stream_output_meter[alsa_format->card][j][0]->
addValue(((double)stream_out_meter)/32768.0);
alsa_stream_output_meter[alsa_format->card][j][1]->
addValue(((double)stream_out_meter)/32768.0);
modulo=alsa_format->channels*2;
for(unsigned i=0;i<(alsa_format->channels/2);i++) {
if(alsa_output_volume[alsa_format->card][i][j]!=0.0) {
for(int k=0;k<(2*n);k++) {
((int16_t *)alsa_format->card_buffer)[modulo*k+4*i+1]+=
(int16_t)(alsa_output_volume[alsa_format->card][i][j]*
(double)(((int16_t *)alsa_buffer)[k]));
((int16_t *)alsa_format->card_buffer)[modulo*k+4*i+3]+=
(int16_t)(alsa_output_volume[alsa_format->card][i][j]*
(double)(((int16_t *)alsa_buffer)[k]));
}
}
}
n*=2;
break;
case 2: case SND_PCM_FORMAT_S32_LE:
n=alsa_play_ring[alsa_format->card][j]-> for(unsigned j=0;j<RD_MAX_STREAMS;j++) {
read(alsa_buffer,alsa_format->buffer_size*2/ if(alsa_playing[alsa_format->card][j]) {
alsa_format->periods)/(2*sizeof(int16_t)); switch(alsa_output_channels[alsa_format->card][j]) {
for(unsigned k=0;k<2;k++) { // Stream Output Meters case 1:
stream_out_meter=0; n=alsa_play_ring[alsa_format->card][j]->
for(int l=0;l<n;l+=2) { read(alsa_buffer,alsa_format->buffer_size/
if(abs(((int16_t *)alsa_buffer)[l+k])>stream_out_meter) { alsa_format->periods)/(2*sizeof(int16_t));
stream_out_meter=abs(((int16_t *)alsa_buffer)[l+k]); stream_out_meter=0;
} for(int k=0;k<n;k++) { // Stream Output Meters
} if(abs(((int16_t *)alsa_buffer)[k])>stream_out_meter) {
alsa_stream_output_meter[alsa_format->card][j][k]-> stream_out_meter=abs(((int16_t *)alsa_buffer)[k]);
addValue(((double)stream_out_meter)/32768.0); }
} }
modulo=alsa_format->channels*2; alsa_stream_output_meter[alsa_format->card][j][0]->
for(unsigned i=0;i<(alsa_format->channels/2);i++) { addValue(((double)stream_out_meter)/32768.0);
if(alsa_output_volume[alsa_format->card][i][j]!=0.0) { alsa_stream_output_meter[alsa_format->card][j][1]->
for(int k=0;k<n;k++) { addValue(((double)stream_out_meter)/32768.0);
((int16_t *)alsa_format->card_buffer)[modulo*k+4*i+1]+= modulo=alsa_format->channels*2;
(int16_t)(alsa_output_volume[alsa_format->card][i][j]* for(unsigned i=0;i<(alsa_format->channels/2);i++) {
(double)(((int16_t *)alsa_buffer)[2*k])); if(alsa_output_volume[alsa_format->card][i][j]!=0.0) {
((int16_t *)alsa_format->card_buffer)[modulo*k+4*i+3]+= for(int k=0;k<(2*n);k++) {
(int16_t)(alsa_output_volume[alsa_format->card][i][j]* ((int16_t *)alsa_format->card_buffer)[modulo*k+4*i+1]+=
(double)(((int16_t *)alsa_buffer)[2*k+1])); (int16_t)(alsa_output_volume[alsa_format->card][i][j]*
} (double)(((int16_t *)alsa_buffer)[k]));
} ((int16_t *)alsa_format->card_buffer)[modulo*k+4*i+3]+=
} (int16_t)(alsa_output_volume[alsa_format->card][i][j]*
break; (double)(((int16_t *)alsa_buffer)[k]));
} }
alsa_output_pos[alsa_format->card][j]+=n; }
if((n==0)&&alsa_eof[alsa_format->card][j]) { }
alsa_stopping[alsa_format->card][j]=true; n*=2;
// Empty the ring buffer break;
while(alsa_play_ring[alsa_format->card][j]->
read(alsa_buffer,alsa_format->buffer_size*2/
alsa_format->periods)/(2*sizeof(int16_t))>0);
}
}
}
n=alsa_format->buffer_size/(2*alsa_format->periods);
// case 2:
// Process Passthroughs n=alsa_play_ring[alsa_format->card][j]->
// read(alsa_buffer,alsa_format->buffer_size*2/
for(unsigned i=0;i<alsa_format->capture_channels;i+=2) { alsa_format->periods)/(2*sizeof(int16_t));
p=alsa_passthrough_ring[alsa_format->card][i/2]-> for(unsigned k=0;k<2;k++) { // Stream Output Meters
read(alsa_format->passthrough_buffer,8*n)/8; stream_out_meter=0;
for(unsigned j=0;j<alsa_format->channels;j+=2) { for(int l=0;l<n;l+=2) {
for(unsigned k=0;k<2;k++) { if(abs(((int16_t *)alsa_buffer)[l+k])>stream_out_meter) {
for(int l=0;l<p;l++) { stream_out_meter=abs(((int16_t *)alsa_buffer)[l+k]);
((int32_t *)alsa_format-> }
card_buffer)[alsa_format->channels*l+j+k]+= }
(int32_t)((double)((int32_t *) alsa_stream_output_meter[alsa_format->card][j][k]->
alsa_format->passthrough_buffer)[2*l+k]* addValue(((double)stream_out_meter)/32768.0);
alsa_passthrough_volume[alsa_format->card][i/2][j/2]); }
} modulo=alsa_format->channels*2;
} for(unsigned i=0;i<(alsa_format->channels/2);i++) {
} if(alsa_output_volume[alsa_format->card][i][j]!=0.0) {
} for(int k=0;k<n;k++) {
((int16_t *)alsa_format->card_buffer)[modulo*k+4*i+1]+=
(int16_t)(alsa_output_volume[alsa_format->card][i][j]*
(double)(((int16_t *)alsa_buffer)[2*k]));
((int16_t *)alsa_format->card_buffer)[modulo*k+4*i+3]+=
(int16_t)(alsa_output_volume[alsa_format->card][i][j]*
(double)(((int16_t *)alsa_buffer)[2*k+1]));
}
}
}
break;
}
alsa_output_pos[alsa_format->card][j]+=n;
if((n==0)&&alsa_eof[alsa_format->card][j]) {
alsa_stopping[alsa_format->card][j]=true;
// Empty the ring buffer
while(alsa_play_ring[alsa_format->card][j]->
read(alsa_buffer,alsa_format->buffer_size*2/
alsa_format->periods)/(2*sizeof(int16_t))>0);
}
}
}
n=alsa_format->buffer_size/(2*alsa_format->periods);
// //
// Process Output Meters // Process Passthroughs
// //
for(unsigned i=0;i<alsa_format->channels;i+=2) { for(unsigned i=0;i<alsa_format->capture_channels;i+=2) {
unsigned port=i/2; p=alsa_passthrough_ring[alsa_format->card][i/2]->
for(unsigned j=0;j<2;j++) { read(alsa_format->passthrough_buffer,8*n)/8;
out_meter[port][j]=0; bool zero_volume = true;
for(unsigned k=0; for (unsigned j=0;j<alsa_format->channels && zero_volume;j+=1) {
k<(alsa_format->buffer_size*2/alsa_format->periods); zero_volume = (alsa_passthrough_volume[alsa_format->card][i/2][j] == 0.0);
k++) { }
if(((int16_t *)alsa_format-> if (!zero_volume) {
card_buffer)[alsa_format->channels*2*k+2*i+1+2*j]> for(unsigned j=0;j<alsa_format->channels;j+=2) {
out_meter[port][j]) { double passthrough_volume = alsa_passthrough_volume[alsa_format->card][i/2][j/2];
out_meter[port][j]= if (passthrough_volume != 0.0) {
((int16_t *)alsa_format-> for(unsigned k=0;k<2;k++) {
card_buffer)[alsa_format->channels*2*k+2*i+1+2*j]; for(int l=0;l<p;l++) {
} ((int32_t *)alsa_format->
} card_buffer)[alsa_format->channels*l+j+k]+=
alsa_output_meter[alsa_format->card][port][j]-> (int32_t)((double)((int32_t *)alsa_format->passthrough_buffer)[2*l+k]*passthrough_volume);
addValue(((double)out_meter[port][j])/32768.0); }
} }
} }
break; }
}
}
default: //
break; // Process Output Meters
//
unsigned buffer_width;
buffer_width = (alsa_format->buffer_size*2/alsa_format->periods);
for(unsigned i=0;i<alsa_format->channels;i+=2) {
unsigned port=i/2;
for(unsigned j=0;j<2;j++) {
out_meter[port][j]=0;
for(unsigned k=0; k<buffer_width; k++) {
int16_t sample = ((int16_t *)alsa_format->
card_buffer)[alsa_format->channels*2*k+2*i+1+2*j];
if (sample > out_meter[port][j]) {
out_meter[port][j] = sample;
}
}
alsa_output_meter[alsa_format->card][port][j]->
addValue(((double)out_meter[port][j])/32768.0);
}
}
break;
default:
break;
} }
int s=snd_pcm_writei(alsa_format->pcm,alsa_format->card_buffer,n); int s=snd_pcm_writei(alsa_format->pcm,alsa_format->card_buffer,n);
if(s!=n) { if(s!=n) {
if(s<0) { if(s<0) {
LogLine(RDConfig::LogNotice, LogLine(RDConfig::LogNotice,
QString().sprintf("*** alsa error %d: %s",-s,snd_strerror(s))); QString().sprintf("*** alsa error %d: %s",-s,snd_strerror(s)));
} }
else { else {
LogLine(RDConfig::LogNotice, LogLine(RDConfig::LogNotice,
QString().sprintf("period size mismatch - wrote %d\n",s)); QString().sprintf("period size mismatch - wrote %d\n",s));
} }
} }
if((snd_pcm_state(alsa_format->pcm)!=SND_PCM_STATE_RUNNING)&& if((snd_pcm_state(alsa_format->pcm)!=SND_PCM_STATE_RUNNING)&&
@ -534,8 +545,8 @@ void AlsaPlay2Callback(struct alsa_format *alsa_format)
snd_pcm_drop (alsa_format->pcm); snd_pcm_drop (alsa_format->pcm);
snd_pcm_prepare(alsa_format->pcm); snd_pcm_prepare(alsa_format->pcm);
LogLine(RDConfig::LogNotice,QString(). LogLine(RDConfig::LogNotice,QString().
sprintf("****** ALSA Playout Xrun - Card: %d ******", sprintf("****** ALSA Playout Xrun - Card: %d ******",
alsa_format->card)); alsa_format->card));
} }
} }
} }