haptics gain before resample

This commit is contained in:
awalol
2026-05-08 23:57:11 +08:00
parent 1119d2f17a
commit 5d32bb6de9
+25 -21
View File
@@ -35,6 +35,7 @@ alignas(8) static uint32_t audio_core1_stack[8192];
queue_t audio_fifo;
static uint8_t opus_buf[200];
critical_section_t opus_cs;
struct audio_raw_element {
float data[512 * 2];
};
@@ -60,24 +61,27 @@ void audio_loop() {
WDL_ResampleSample *in_buf;
int nframes = resampler.ResamplePrepare(frames, OUTPUT_CHANNELS, &in_buf);
float gain = mute[0] ? 0.0f : powf(10.0f, get_config().speaker_volume / 20.0f);
const float audio_gain = mute[0] ? 0.0f : powf(10.0f, get_config().speaker_volume / 20.0f);
const float haptics_gain = get_config().haptics_gain;
for (int i = 0; i < nframes; i++) {
audio_buf[audio_buf_pos++] = raw[i * INPUT_CHANNELS] / 32768.0f * gain;
audio_buf[audio_buf_pos++] = raw[i * INPUT_CHANNELS + 1] / 32768.0f * gain;
audio_buf[audio_buf_pos++] = raw[i * INPUT_CHANNELS] / 32768.0f * audio_gain;
audio_buf[audio_buf_pos++] = raw[i * INPUT_CHANNELS + 1] / 32768.0f * audio_gain;
if (audio_buf_pos == 512 * 2) {
static audio_raw_element element{};
memcpy(element.data,audio_buf,512 * 2 * 4);
if (queue_is_full(&audio_fifo)){
memcpy(element.data, audio_buf, 512 * 2 * 4);
if (queue_is_full(&audio_fifo)) {
queue_try_remove(&audio_fifo,NULL);
}
if (!queue_try_add(&audio_fifo,&element)) {
if (!queue_try_add(&audio_fifo, &element)) {
printf("[Audio] Warning: audio_fifo add failed\n");
}
audio_buf_pos = 0;
}
in_buf[i * 2] = (WDL_ResampleSample) raw[i * INPUT_CHANNELS + 2] / 32768.0f;
in_buf[i * 2 + 1] = (WDL_ResampleSample) raw[i * INPUT_CHANNELS + 3] / 32768.0f;
in_buf[i * 2] = static_cast<WDL_ResampleSample>(clamp(raw[i * INPUT_CHANNELS + 2] / 32768.0f * haptics_gain,
-1.0f, 1.0f));
in_buf[i * 2 + 1] = static_cast<WDL_ResampleSample>(clamp(raw[i * INPUT_CHANNELS + 3] / 32768.0f * haptics_gain,
-1.0f, 1.0f));
}
// 3. 48kHz -> 3kHz 重采样
@@ -89,8 +93,8 @@ void audio_loop() {
// 4. 转换为int8并缓冲,满64字节即组包发送
for (int i = 0; i < out_frames; i++) {
int val_l = (int) (out_buf[i * 2] * 127.0f * max(get_config().haptics_gain,1.0f));
int val_r = (int) (out_buf[i * 2 + 1] * 127.0f * max(get_config().haptics_gain,1.0f));
int val_l = static_cast<int>(out_buf[i * 2] * 127.0f);
int val_r = static_cast<int>(out_buf[i * 2 + 1] * 127.0f);
haptic_buf[haptic_buf_pos++] = (int8_t) clamp(val_l, -128, 127); // 似乎clamp有点多余?还是以防万一吧
haptic_buf[haptic_buf_pos++] = (int8_t) clamp(val_r, -128, 127);
@@ -117,7 +121,7 @@ void audio_loop() {
pkt[77] = (plug_headset ? 0x16 : 0x13) | 0 << 6 | 1 << 7; // Speaker: 0x13
pkt[78] = 200;
critical_section_enter_blocking(&opus_cs);
memcpy(pkt + 79,opus_buf,200);
memcpy(pkt + 79, opus_buf, 200);
critical_section_exit(&opus_cs);
bt_write(pkt, sizeof(pkt));
@@ -130,9 +134,9 @@ void audio_init() {
resampler.SetRates(48000, 3000);
resampler.SetFeedMode(true);
resampler.Prealloc(2, 24, 6);
queue_init(&audio_fifo,sizeof(audio_raw_element),2);
queue_init(&audio_fifo, sizeof(audio_raw_element), 2);
critical_section_init(&opus_cs);
multicore_launch_core1_with_stack(core1_entry,audio_core1_stack,sizeof(audio_core1_stack));
multicore_launch_core1_with_stack(core1_entry, audio_core1_stack, sizeof(audio_core1_stack));
}
static OpusEncoder *encoder;
@@ -140,7 +144,7 @@ static WDL_Resampler resampler_audio;
void core1_entry() {
int error = 0;
encoder = opus_encoder_create(48000,2,OPUS_APPLICATION_AUDIO,&error);
encoder = opus_encoder_create(48000, 2,OPUS_APPLICATION_AUDIO, &error);
if (error != 0) {
printf("[Audio] OpusEncoder create failed\n");
return;
@@ -149,27 +153,27 @@ void core1_entry() {
opus_encoder_ctl(encoder,OPUS_SET_BITRATE(200 * 8 * 100));
opus_encoder_ctl(encoder,OPUS_SET_VBR(false));
opus_encoder_ctl(encoder,OPUS_SET_COMPLEXITY(0)); // max 4
resampler_audio.SetMode(true,0,false);
resampler_audio.SetRates(51200,48000);
resampler_audio.SetMode(true, 0, false);
resampler_audio.SetRates(51200, 48000);
resampler_audio.SetFeedMode(true);
resampler_audio.Prealloc(2, 512, 480);
while (true) {
static audio_raw_element audio_element{};
queue_remove_blocking(&audio_fifo,&audio_element);
queue_remove_blocking(&audio_fifo, &audio_element);
// 将 512 frames 重采样成 480 frames 以解决噪音问题。感谢 @Junhoo
WDL_ResampleSample *in_buf;
int nframes = resampler_audio.ResamplePrepare(512, 2, &in_buf);
for (int i = 0; i < nframes * 2;i++) {
for (int i = 0; i < nframes * 2; i++) {
in_buf[i] = audio_element.data[i];
}
static WDL_ResampleSample out_buf[480 * 2];
resampler_audio.ResampleOut(out_buf,nframes,480,2);
resampler_audio.ResampleOut(out_buf, nframes, 480, 2);
static uint8_t out[200];
(void)opus_encode_float(encoder,out_buf,480,out,200);
(void) opus_encode_float(encoder, out_buf, 480, out, 200);
critical_section_enter_blocking(&opus_cs);
memcpy(opus_buf,out,200);
memcpy(opus_buf, out, 200);
critical_section_exit(&opus_cs);
}
}