📄 audio.c
字号:
}static float dB_to_normalized(float val, float lo, float hi){ float linlo; if (hi <= lo) return(1.0); linlo = dB_to_linear(lo); return((dB_to_linear(val) - linlo) / (dB_to_linear(hi) - linlo));}static float normalized_to_dB(float val_norm, float lo_dB, float hi_dB){ if (hi_dB <= lo_dB) return(0.0); return(lo_dB + (hi_dB - lo_dB) * val_norm);}int mus_audio_mixer_read(int ur_dev, int field, int chan, float *val){ ALpv x[4]; ALparamInfo pinf; ALfixed g[MAX_CHANNELS]; int rv = 0, i, dev; start_sgi_print(); dev = MUS_AUDIO_DEVICE(ur_dev); if (field != MUS_AUDIO_PORT) { rv = to_al_device(dev); if (!rv) RETURN_ERROR_EXIT(MUS_AUDIO_DEVICE_NOT_AVAILABLE, -1, mus_format("can't read %s field %d (%s)", mus_audio_device_name(dev), field, mus_audio_device_name(field))); } switch (field) { case MUS_AUDIO_PORT: /* in this case, chan == length of incoming val array. Number of devices is returned as val[0], * and the rest of the available area (if needed) is filled with the device ids. */ i = 0; if (alGetResourceByName(AL_SYSTEM, "Microphone", AL_DEVICE_TYPE) != 0) {if ((i + 1) < chan) val[i + 1] = MUS_AUDIO_MICROPHONE; i++;} if (alGetResourceByName(AL_SYSTEM, "Analog Out", AL_DEVICE_TYPE) != 0) {if ((i + 1) < chan) val[i + 1] = MUS_AUDIO_DAC_OUT; i++;} if (alGetResourceByName(AL_SYSTEM, "ADAT In", AL_DEVICE_TYPE) != 0) {if ((i + 1) < chan) val[i + 1] = MUS_AUDIO_ADAT_IN; i++;} if (alGetResourceByName(AL_SYSTEM, "AES In", AL_DEVICE_TYPE) != 0) {if ((i + 1) < chan) val[i + 1] = MUS_AUDIO_AES_IN; i++;} if (alGetResourceByName(AL_SYSTEM, "ADAT Out", AL_DEVICE_TYPE) != 0) {if ((i + 1) < chan) val[i + 1] = MUS_AUDIO_ADAT_OUT; i++;} if (alGetResourceByName(AL_SYSTEM, "AES Out", AL_DEVICE_TYPE) != 0) {if ((i + 1) < chan) val[i + 1] = MUS_AUDIO_AES_OUT; i++;} if (alGetResourceByName(AL_SYSTEM, "Line In", AL_DEVICE_TYPE) != 0) {if ((i + 1) < chan) val[i + 1] = MUS_AUDIO_LINE_IN; i++;} /* if (alGetResourceByName(AL_SYSTEM, "DAC2 In", AL_DEVICE_TYPE) != 0) {if ((i + 1) < chan) val[i + 1] = MUS_AUDIO_DIGITAL_IN; i++;} */ val[0] = i; break; case MUS_AUDIO_FORMAT: val[0] = 1; if (chan > 1) val[1] = MUS_BSHORT; break; case MUS_AUDIO_CHANNEL: x[0].param = AL_CHANNELS; if (alGetParams(rv, x, 1) == -1) RETURN_ERROR_EXIT(MUS_AUDIO_READ_ERROR, -1, mus_format("can't read channel setting of %s", mus_audio_device_name(dev))); val[0] = (float)(x[0].value.i); break; case MUS_AUDIO_SRATE: x[0].param = AL_RATE; if (alGetParams(rv, x, 1) == -1) RETURN_ERROR_EXIT(MUS_AUDIO_READ_ERROR, -1, mus_format("can't read srate setting of %s", mus_audio_device_name(dev))); val[0] = (float)(x[0].value.i); break; case MUS_AUDIO_AMP: if (alGetParamInfo(rv, AL_GAIN, &pinf) == -1) RETURN_ERROR_EXIT(MUS_AUDIO_READ_ERROR, -1, mus_format("can't read gain settings of %s", mus_audio_device_name(dev))); if (pinf.min.ll == pinf.max.ll) RETURN_ERROR_EXIT(MUS_AUDIO_AMP_NOT_AVAILABLE, -1, mus_format("%s's gain apparently can't be set", mus_audio_device_name(dev))); /* this ridiculous thing is in dB with completely arbitrary min and max values */ x[0].param = AL_GAIN; x[0].value.ptr = g; x[0].sizeIn = MAX_CHANNELS; alGetParams(rv, x, 1); if (x[0].sizeOut <= chan) RETURN_ERROR_EXIT(MUS_AUDIO_CHANNELS_NOT_AVAILABLE, -1, mus_format("can't read gain settings of %s channel %d", mus_audio_device_name(dev), chan)); val[0] = dB_to_normalized(alFixedToDouble(g[chan]), alFixedToDouble(pinf.min.ll), alFixedToDouble(pinf.max.ll)); break; default: RETURN_ERROR_EXIT(MUS_AUDIO_CANT_READ, -1, mus_format("can't read %s setting of %s", mus_audio_device_name(field), mus_audio_device_name(dev))); break; } end_sgi_print(); return(MUS_NO_ERROR);}int mus_audio_mixer_write(int ur_dev, int field, int chan, float *val){ /* each field coming in assumes 0.0 to 1.0 as the range */ ALpv x[4]; ALparamInfo pinf; ALfixed g[MAX_CHANNELS]; int rv, dev; start_sgi_print(); dev = MUS_AUDIO_DEVICE(ur_dev); rv = to_al_device(dev); if (!rv) RETURN_ERROR_EXIT(MUS_AUDIO_DEVICE_NOT_AVAILABLE, -1, mus_format("can't write %s field %d (%s)", mus_audio_device_name(dev), field, mus_audio_device_name(field))); switch (field) { case MUS_AUDIO_SRATE: x[0].param = AL_RATE; x[0].value.i = (int)val[0]; x[1].param = AL_MASTER_CLOCK; x[1].value.i = AL_CRYSTAL_MCLK_TYPE; alSetParams(rv, x, 2); break; case MUS_AUDIO_AMP: /* need to change normalized linear value into dB between (dB) lo and hi */ if (alGetParamInfo(rv, AL_GAIN, &pinf) == -1) RETURN_ERROR_EXIT(MUS_AUDIO_READ_ERROR, -1, mus_format("can't write gain settings of %s", mus_audio_device_name(dev))); /* I think we need to read all channels here, change the one we care about, then write all channels */ x[0].param = AL_GAIN; x[0].value.ptr = g; x[0].sizeIn = MAX_CHANNELS; alGetParams(rv, x, 1); if (x[0].sizeOut <= chan) RETURN_ERROR_EXIT(MUS_AUDIO_CHANNELS_NOT_AVAILABLE, -1, mus_format("can't write gain settings of %s channel %d", mus_audio_device_name(dev), chan)); g[chan] = alDoubleToFixed(normalized_to_dB(val[0], alFixedToDouble(pinf.min.ll), alFixedToDouble(pinf.max.ll))); if (alSetParams(rv, x, 1) == -1) RETURN_ERROR_EXIT(MUS_AUDIO_WRITE_ERROR, -1, mus_format("can't write gain settings of %s", mus_audio_device_name(dev))); break; default: RETURN_ERROR_EXIT(MUS_AUDIO_CANT_READ, -1, mus_format("can't write %s setting of %s", mus_audio_device_name(field), mus_audio_device_name(dev))); break; } end_sgi_print(); return(MUS_NO_ERROR);}#define STRING_SIZE 32static void dump_resources(ALvalue *x, int rv){ ALpv y[4]; ALparamInfo pinf; ALfixed g[MAX_CHANNELS]; char dn[STRING_SIZE]; char dl[STRING_SIZE]; int i, k; ALvalue z[16]; int nres; for (i = 0; i < rv; i++) { y[0].param = AL_LABEL; y[0].value.ptr = dl; y[0].sizeIn = STRING_SIZE; y[1].param = AL_NAME; y[1].value.ptr = dn; y[1].sizeIn = STRING_SIZE; y[2].param = AL_CHANNELS; y[3].param = AL_RATE; alGetParams(x[i].i, y, 5); if (alIsSubtype(AL_DEVICE_TYPE, x[i].i)) { alGetParamInfo(x[i].i, AL_GAIN, &pinf); mus_snprintf(audio_strbuf, PRINT_BUFFER_SIZE, "\nDevice: %s (%s), srate: %d, chans: %d", dn, dl, y[3].value.i, y[2].value.i); pprint(audio_strbuf); if (pinf.min.ll != pinf.max.ll) { ALpv yy; yy.param = AL_GAIN; yy.value.ptr = g; yy.sizeIn = MAX_CHANNELS; alGetParams(x[i].i, &yy, 1); pprint(" amps:["); for (k = 0; k < yy.sizeOut; k++) { mus_snprintf(audio_strbuf, PRINT_BUFFER_SIZE, "%.2f", dB_to_normalized(alFixedToDouble(g[k]), alFixedToDouble(pinf.min.ll), alFixedToDouble(pinf.max.ll))); pprint(audio_strbuf); if (k < (yy.sizeOut - 1)) pprint(" "); } pprint("]"); } pprint("\n"); if ((nres= alQueryValues(x[i].i, AL_INTERFACE, z, 16, 0, 0)) >= 0) dump_resources(z, nres); else mus_snprintf(audio_strbuf, PRINT_BUFFER_SIZE, "query failed: %s\n", alGetErrorString(oserror())); pprint(audio_strbuf); } else { mus_snprintf(audio_strbuf, PRINT_BUFFER_SIZE, " %s (%s), chans: %d\n", dn, dl, y[2].value.i); pprint(audio_strbuf); } }}static void describe_audio_state_1(void){ int rv; ALvalue x[16]; pprint("Devices and Interfaces on this system:\n"); rv= alQueryValues(AL_SYSTEM, AL_DEVICES, x, 16, 0, 0); if (rv > 0) dump_resources(x, rv);}#else/* old audio library */#define MAX_VOLUME 255static int decode_field(int dev, int field, int chan){ switch (dev) { case MUS_AUDIO_DEFAULT: case MUS_AUDIO_DAC_OUT: case MUS_AUDIO_DUPLEX_DEFAULT: case MUS_AUDIO_SPEAKERS: switch (field) { case MUS_AUDIO_AMP: return((chan == 0) ? AL_LEFT_SPEAKER_GAIN : AL_RIGHT_SPEAKER_GAIN); break; case MUS_AUDIO_SRATE: return(AL_OUTPUT_RATE); break; } break; case MUS_AUDIO_LINE_OUT: switch (field) { case MUS_AUDIO_SRATE: return(AL_OUTPUT_RATE); /* ? */ break; } break; case MUS_AUDIO_DIGITAL_OUT: if (field == MUS_AUDIO_SRATE) return(AL_OUTPUT_RATE); break; case MUS_AUDIO_DIGITAL_IN: if (field == MUS_AUDIO_SRATE) return(AL_INPUT_RATE); break; case MUS_AUDIO_LINE_IN: if (field == MUS_AUDIO_AMP) return((chan == 0) ? AL_LEFT_INPUT_ATTEN : AL_RIGHT_INPUT_ATTEN); else if (field == MUS_AUDIO_SRATE) return(AL_INPUT_RATE); break; case MUS_AUDIO_MICROPHONE: if (field == MUS_AUDIO_AMP) return((chan == 0) ? AL_LEFT2_INPUT_ATTEN : AL_RIGHT2_INPUT_ATTEN); else if (field == MUS_AUDIO_SRATE) return(AL_INPUT_RATE); break; } return(MUS_ERROR);}int mus_audio_mixer_read(int ur_dev, int field, int chan, float *val){ long pb[4]; long fld; int dev, err = MUS_NO_ERROR; start_sgi_print(); dev = MUS_AUDIO_DEVICE(ur_dev); switch (field) { case MUS_AUDIO_CHANNEL: val[0] = 4; break; case MUS_AUDIO_FORMAT: val[0] = 1; if (chan > 1) val[1] = MUS_BSHORT; break; case MUS_AUDIO_PORT: /* how to tell which machine we're on? */ val[0] = 4; if (chan > 1) val[1] = MUS_AUDIO_LINE_IN; if (chan > 2) val[2] = MUS_AUDIO_MICROPHONE; if (chan > 3) val[3] = MUS_AUDIO_DIGITAL_IN; if (chan > 4) val[4] = MUS_AUDIO_DAC_OUT; /* does this order work for digital input as well? (i.e. does it replace the microphone)? */ break; case MUS_AUDIO_AMP: fld = decode_field(dev, field, chan); if (fld != MUS_ERROR) { pb[0] = fld; if (ALgetparams(AL_DEFAULT_DEVICE, pb, 2)) RETURN_ERROR_EXIT(MUS_AUDIO_READ_ERROR, -1, mus_format("can't read gain settings of %s", mus_audio_device_name(dev))); if ((fld == AL_LEFT_SPEAKER_GAIN) || (fld == AL_RIGHT_SPEAKER_GAIN)) val[0] = ((float)pb[1]) / ((float)MAX_VOLUME); else val[0] = 1.0 - ((float)pb[1]) / ((float)MAX_VOLUME); } else err = MUS_ERROR; break; case MUS_AUDIO_SRATE: fld = decode_field(dev, field, chan); if (fld != MUS_ERROR) { pb[0] = fld; if (ALgetparams(AL_DEFAULT_DEVICE, pb, 2)) RETURN_ERROR_EXIT(MUS_AUDIO_READ_ERROR, -1, mus_format("can't read srate setting of %s", mus_audio_device_name(dev))); val[0] = pb[1]; } else err = MUS_ERROR; break; default: err = MUS_ERROR; break; } if (err == MUS_ERROR) RETURN_ERROR_EXIT(MUS_AUDIO_CANT_READ, -1, mus_format("can't read %s setting of %s", mus_audio_device_name(field), mus_audio_device_name(dev))); end_sgi_print(); return(MUS_NO_ERROR);}int mus_audio_mixer_write(int ur_dev, int field, int chan, float *val){ long pb[4]; long fld; int dev, err = MUS_NO_ERROR; start_sgi_print(); dev = MUS_AUDIO_DEVICE(ur_dev); switch (field) { case MUS_AUDIO_PORT: if (dev == MUS_AUDIO_DEFAULT) { pb[0] = AL_CHANNEL_MODE; pb[1] = ((chan == MUS_AUDIO_DIGITAL_IN) ? AL_STEREO : AL_4CHANNEL); pb[2] = AL_INPUT_SOURCE; pb[3] = ((chan == MUS_AUDIO_DIGITAL_IN) ? AL_INPUT_DIGITAL : AL_INPUT_MIC); if (ALsetparams(AL_DEFAULT_DEVICE, pb, 4)) RETURN_ERROR_EXIT(MUS_AUDIO_WRITE_ERROR, -1, mus_format("can't set mode and source of %s", mus_audio_device_name(dev))); } else err = MUS_ERROR; break; case MUS_AUDIO_CHANNEL: if (dev == MUS_AUDIO_MICROPHONE) { pb[0] = AL_MIC_MODE; pb[1] = ((chan == 2) ? AL_STEREO : AL_MONO); if (ALsetparams(AL_DEFAULT_DEVICE, pb, 2)) RETURN_ERROR_EXIT(MUS_AUDIO_WRITE_ERROR, -1, mus_format("can't set microphone to be %s", (chan == 2) ? "stereo" : "mono")); } else { if (dev == MUS_AUDIO_DEFAULT) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -