Skip to content

Commit

Permalink
Work in progress, doesn't compile
Browse files Browse the repository at this point in the history
  • Loading branch information
mikebrady committed Nov 5, 2015
1 parent 70d1fd3 commit 4c70223
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 78 deletions.
12 changes: 6 additions & 6 deletions audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,9 @@
#include <libconfig.h>

typedef struct {
double airplay_volume;
double current_volume_dB;
int minimum_volume_dB;
int maximum_volume_dB;
int has_true_mute;
int is_muted;
int valid;
int32_t minimum_volume_dB;
int32_t maximum_volume_dB;
} audio_parameters;

typedef struct {
Expand Down Expand Up @@ -42,6 +38,10 @@ typedef struct {

// may be NULL, in which case soft volume parameters are used
void (*parameters)(audio_parameters *info);

// may be NULL, in which case software muting is used.
void (*mute)(int do_mute);

} audio_output;

audio_output *audio_get_output(char *name);
Expand Down
35 changes: 12 additions & 23 deletions audio_alsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ static uint32_t delay(void);
static void volume(double vol);
static void linear_volume(double vol);
static void parameters(audio_parameters *info);
static void mute(int do_mute);
static int has_mute = 0;
static double set_volume;

Expand Down Expand Up @@ -234,13 +235,6 @@ static int init(int argc, char **argv) {
}
debug(1, "Hardware mixer has dB volume from %f to %f.", (1.0 * alsa_mix_mindb) / 100.0,
(1.0 * alsa_mix_maxdb) / 100.0);
if (config.volume_range_db) {
long suggested_alsa_min_db = alsa_mix_maxdb - (long)trunc(config.volume_range_db*100);
if (suggested_alsa_min_db > alsa_mix_mindb)
alsa_mix_mindb = suggested_alsa_min_db;
else
inform("The volume_range_db setting, %f is greater than the native range of the mixer %f, so it is ignored.",config.volume_range_db,(alsa_mix_maxdb-alsa_mix_mindb)/100.0);
}
} else {
// use the linear scale and do the db conversion ourselves
debug(1, "note: the hardware mixer specified -- \"%s\" -- does not have a dB volume scale, so it can't be used.",alsa_mix_ctrl);
Expand Down Expand Up @@ -447,35 +441,30 @@ static void stop(void) {
}

static void parameters(audio_parameters *info) {
info->has_true_mute = has_mute;
info->is_muted = ((has_mute) && (set_volume == -144.0));
info->minimum_volume_dB = alsa_mix_mindb;
info->maximum_volume_dB = alsa_mix_maxdb;
info->airplay_volume = set_volume;
info->current_volume_dB = vol2attn(set_volume, alsa_mix_maxdb, alsa_mix_mindb);
}

static void volume(double vol) {
// debug(1,"Volume called %f.",vol);
set_volume = vol;
double vol_setting = vol2attn(vol, alsa_mix_maxdb, alsa_mix_mindb);
// debug(1,"Setting volume db to %f, for volume input of %f.",vol_setting/100,vol);
if (snd_mixer_selem_set_playback_dB_all(alsa_mix_elem, vol_setting, -1) != 0)
if (snd_mixer_selem_set_playback_dB_all(alsa_mix_elem, vol, -1) != 0)
die("Failed to set playback dB volume");
if (has_mute)
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, (vol != -144.0));
}

static void linear_volume(double vol) {
set_volume = vol;
double vol_setting = vol2attn(vol, 0, alsa_mix_mindb)/2000;
// debug(1,"Adjusted volume is %f.",vol_setting);
double linear_volume = pow(10, vol_setting);
double linear_volume = pow(10, vol);
// debug(1,"Linear volume is %f.",linear_volume);
long int_vol = alsa_mix_minv + (alsa_mix_maxv - alsa_mix_minv) * linear_volume;
// debug(1,"Setting volume to %ld, for volume input of %f.",int_vol,vol);
if (snd_mixer_selem_set_playback_volume_all(alsa_mix_elem, int_vol) != 0)
die("Failed to set playback volume");
if (has_mute)
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, (vol != -144.0));
}

static void mute(int do_mute) {
if (has_mute) {
if (do_mute)
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 0);
else
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 1);
}
}
3 changes: 2 additions & 1 deletion audio_ao.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,5 @@ audio_output audio_ao = {.name = "ao",
.delay = NULL,
.play = &play,
.volume = NULL,
.parameters = NULL};
.parameters = NULL,
.mute = NULL};
3 changes: 2 additions & 1 deletion audio_dummy.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,5 @@ audio_output audio_dummy = {.name = "dummy",
.delay = NULL,
.play = &play,
.volume = NULL,
.parameters = NULL};
.parameters = NULL,
.mute = NULL};
3 changes: 2 additions & 1 deletion audio_pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,5 @@ audio_output audio_pipe = {.name = "pipe",
.delay = NULL,
.play = &play,
.volume = NULL,
.parameters = NULL};
.parameters = NULL,
.mute = NULL};
3 changes: 2 additions & 1 deletion audio_pulse.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,5 @@ audio_output audio_pulse = {.name = "pulse",
.delay = NULL,
.play = &play,
.volume = NULL,
.parameters = NULL};
.parameters = NULL,
.mute = NULL};
3 changes: 2 additions & 1 deletion audio_sndio.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,5 @@ audio_output audio_sndio = {.name = "sndio",
.delay = NULL,
.play = &play,
.volume = &volume,
.parameters = NULL};
.parameters = NULL,
.mute= NULL};
3 changes: 2 additions & 1 deletion audio_stdout.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,5 @@ audio_output audio_stdout = {.name = "stdout",
.delay = NULL,
.play = &play,
.volume = NULL,
.parameters = NULL};
.parameters = NULL,
.mute = NULL};
2 changes: 1 addition & 1 deletion common.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ uint32_t uatoi(const char *nptr);
shairport_cfg config;
config_t config_file_stuff;

uint32_t buffer_occupancy;
int32_t buffer_occupancy; // allow it to be negative because seq_diff may be negative
int64_t session_corrections;
uint32_t play_segment_reference_frame;
uint64_t play_segment_reference_frame_remote_time;
Expand Down
104 changes: 62 additions & 42 deletions player.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ static uint64_t packet_count = 0;
static int32_t last_seqno_read;

// interthread variables
static double software_mixer_volume = 1.0;
static int fix_volume = 0x10000;
static pthread_mutex_t vol_mutex = PTHREAD_MUTEX_INITIALIZER;

Expand Down Expand Up @@ -452,7 +451,7 @@ static abuf_t *buffer_get_frame(void) {
if (ab_synced) {
do {
curframe = audio_buffer + BUFIDX(ab_read);
if (curframe->ready) {
if ((ab_read!=ab_write) && (curframe->ready)) { // it could be synced and empty, under exceptional circumstances, with the frame unused, thus apparently ready

if (curframe->sequence_number != ab_read) {
// some kind of sync problem has occurred.
Expand Down Expand Up @@ -838,7 +837,7 @@ static int stuff_buffer_soxr(short *inptr, short *outptr, int stuff) {
}

// finally, adjust the volume, if necessary
if (software_mixer_volume != 1.0) {
if (fix_volume != 65536.0) {
// pthread_mutex_lock(&vol_mutex);
op = outptr;
for (i = 0; i < frame_size + stuff; i++) {
Expand Down Expand Up @@ -1171,15 +1170,15 @@ static void *player_thread_func(void *arg) {
inform("Sync error: %.1f (frames); net correction: %.1f (ppm); corrections: %.1f "
"(ppm); missing packets %llu; late packets %llu; too late packets %llu; "
"resend requests %llu; min DAC queue size %lli, min and max buffer occupancy "
"%u and %u.",
"%d and %d.",
moving_average_sync_error, moving_average_correction * 1000000 / 352,
moving_average_insertions_plus_deletions * 1000000 / 352, missing_packets,
late_packets, too_late_packets, resend_requests, minimum_dac_queue_size,
minimum_buffer_occupancy, maximum_buffer_occupancy);
else
inform("Synchronisation disabled. Missing packets %llu; late packets %llu; too late packets %llu; "
"resend requests %llu; min and max buffer occupancy "
"%u and %u.",
"%d and %d.",
missing_packets,
late_packets, too_late_packets, resend_requests,
minimum_buffer_occupancy, maximum_buffer_occupancy);
Expand All @@ -1201,7 +1200,7 @@ static void *player_thread_func(void *arg) {
}

// takes the volume as specified by the airplay protocol
void player_volume(double f) {
void player_volume(double airplay_volume) {

// The volume ranges -144.0 (mute) or -30 -- 0. See
// http:https://git.zx2c4.com/Airtunes2/about/#setting-volume
Expand All @@ -1218,50 +1217,71 @@ void player_volume(double f) {
// or 20 times the log of the ratio. Then multiplied by 100 for convenience.
// Thus, we ask our vol2attn function for an appropriate dB between -96.3 and 0 dB and translate
// it back to a number.

double linear_volume = 0.0;

if (config.output->volume) {
// debug(1,"Set volume to %f.",f);
config.output->volume(f); // volume will be sent as metadata by the config.output device
linear_volume = 1.0; // no attenuation needed -- this value is used as a flag to avoid calculations
}

if (config.output->parameters)


// get the audio parameters

int32_t min,max;

if (config.output->parameters) {
config.output->parameters(&audio_information);
else {
long mindb = -9630;
if (config.volume_range_db) {
long suggested_alsa_min_db = -(long)trunc(config.volume_range_db*100);
if (suggested_alsa_min_db > mindb)
mindb = suggested_alsa_min_db;
else
inform("The volume_range_db setting, %f is greater than the native range of the mixer %f, so it is ignored.",config.volume_range_db,mindb/100.0);
}
double scaled_volume = vol2attn(f, 0, mindb);
linear_volume = pow(10, scaled_volume / 2000);
audio_information.airplay_volume = f;
audio_information.minimum_volume_dB = mindb;
audio_information.maximum_volume_dB = 0;
audio_information.current_volume_dB = scaled_volume;
audio_information.has_true_mute = 0;
audio_information.is_muted = 0;
// debug(1,"Minimum software volume set to %d centi-dB",f,mindb);
max = audio_information.maximum_volume_dB;
min = audio_information.minimum_volume_dB;
} else {
max = 0;
min = -9630;
}
audio_information.valid = 1;
// debug(1,"Software volume set to %f on scale with a %f dB",f,linear_volume);

double temp_fix_volume = 65536.0;
double scaled_volume;

if (airplay_volume==-144.0) { // if we are muting
scaled_volume = min; // this is just for the metadata
if (config.output->mute)
config.output->mute(1); // use real mute if it's there
else if (config.output->volume) {
config.output_.volume(min); // otherwise set the output to the lowest value
temp_fix_volume = 0; // and set the software multiplier to 0.
}
} else { // not muting

if (config.volume_range_db) {
int32_t possible_min = max - (int)trunc(config.volume_range_db*100);
if (possible_min > min)
min = possible_min;
}

// now we have the true desired range, get the volume that is being set
scaled_volume = vol2attn(airplay_volume, max, min);
double software_volume = 0; dB or attenuation

if (config.output->volume) {
if (scaled_volume>=min) {
config.output->volume(scaled_volume);
} else {
config.output->volume(min);
software_volume = scaled_volume-min; // this is the attenuation in dB needed in software
}
} else {
software_volume = scaled_volume;
}
if (config.output->mute) // if there is hardware mute...
config.output->mute(0); // turn it off
temp_fix_volume = 65536.0 * pow(10, software_volume / 2000);
}
// debug(1,"Software volume set to %f on scale with a %f dB",airplay_volume,pow(10, software_volume / 2000));
pthread_mutex_lock(&vol_mutex);
software_mixer_volume = linear_volume;
fix_volume = 65536.0 * software_mixer_volume;
fix_volume = temp_fix_volume;
pthread_mutex_unlock(&vol_mutex);

#ifdef CONFIG_METADATA
char *dv = malloc(128); // will be freed in the metadata thread
if (dv) {
memset(dv, 0, 128);
snprintf(dv, 127, "%.2f,%.2f,%.2f,%.2f", audio_information.airplay_volume,
audio_information.current_volume_dB / 100.0,
audio_information.minimum_volume_dB / 100.0,
audio_information.maximum_volume_dB / 100.0);
snprintf(dv, 127, "%.2f,%.2f,%.2f,%.2f", airplay_volume,
scaled_volume / 100.0,
min / 100.0,
max / 100.0);
send_ssnc_metadata('pvol', dv, strlen(dv), 1);
}
#endif
Expand Down

0 comments on commit 4c70223

Please sign in to comment.