Skip to content

Commit 2bf6aef

Browse files
committed
fix resample audio
1 parent 260d8a8 commit 2bf6aef

File tree

1 file changed

+81
-16
lines changed

1 file changed

+81
-16
lines changed

src/libs/audio-util/src/Util.cpp

Lines changed: 81 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include <audio-util/Util.h>
2-
32
#include <iostream>
3+
#include <memory>
44
#include <soxr.h>
55
#include "FlacDecoder.h"
66
#include "Mp3Decoder.h"
@@ -50,6 +50,10 @@ namespace AudioUtil
5050
const int original_src_channels = srcHandle.channels();
5151
const int original_src_samplerate = srcHandle.samplerate();
5252

53+
// 确定输入数据类型
54+
int input_format = sf_vio_in.info.format & SF_FORMAT_SUBMASK;
55+
bool is_float_input = (input_format == SF_FORMAT_FLOAT || input_format == SF_FORMAT_DOUBLE);
56+
5357
SF_VIO sf_vio_out;
5458
sf_vio_out.info = sf_vio_in.info;
5559
sf_vio_out.info.channels = tar_channel;
@@ -59,21 +63,43 @@ namespace AudioUtil
5963
// 计算估计的输出帧数
6064
const double ratio = static_cast<double>(tar_samplerate) / original_src_samplerate;
6165
const sf_count_t estimated_frames = static_cast<sf_count_t>(srcHandle.frames() * ratio + 0.5);
62-
const size_t estimated_size = estimated_frames * tar_channel * sizeof(float);
66+
const size_t estimated_size = static_cast<size_t>(estimated_frames * tar_channel * sizeof(float));
6367

6468
sf_vio_out.data.byteArray.reserve(estimated_size);
6569

6670
// 创建输出VIO的SndfileHandle
67-
auto dstHandle = SndfileHandle(sf_vio_out.vio, &sf_vio_out.data, SFM_WRITE, sf_vio_in.info.format, tar_channel,
68-
tar_samplerate);
71+
auto dstHandle = SndfileHandle(sf_vio_out.vio, &sf_vio_out.data, SFM_WRITE, (SF_FORMAT_WAV | SF_FORMAT_FLOAT),
72+
tar_channel, tar_samplerate);
6973
if (!dstHandle) {
7074
msg = "Failed to open output VIO: " + std::string(sf_strerror(nullptr));
7175
return {};
7276
}
7377

74-
// 创建 SoX 重采样器
78+
// 创建 SoX 重采样器 - 使用正确的I/O规格
7579
soxr_error_t error = nullptr;
76-
const auto io_spec = soxr_io_spec(SOXR_FLOAT32_I, SOXR_FLOAT32_I);
80+
soxr_io_spec_t io_spec;
81+
82+
// 根据输入数据类型设置正确的I/O规格
83+
if (is_float_input) {
84+
io_spec = soxr_io_spec(SOXR_FLOAT32_I, SOXR_FLOAT32_I);
85+
} else {
86+
// 对于整数格式,使用正确的位深度
87+
int input_bits = 0;
88+
if (input_format == SF_FORMAT_PCM_16)
89+
input_bits = 16;
90+
else if (input_format == SF_FORMAT_PCM_24)
91+
input_bits = 24;
92+
else if (input_format == SF_FORMAT_PCM_32)
93+
input_bits = 32;
94+
95+
if (input_bits == 16) {
96+
io_spec = soxr_io_spec(SOXR_INT16_I, SOXR_FLOAT32_I);
97+
} else {
98+
// 24位和32位数据都使用INT32处理
99+
io_spec = soxr_io_spec(SOXR_INT32_I, SOXR_FLOAT32_I);
100+
}
101+
}
102+
77103
const auto quality_spec = soxr_quality_spec(SOXR_HQ, 0);
78104
const auto runtime_spec = soxr_runtime_spec(1); // 单线程
79105

@@ -92,21 +118,55 @@ namespace AudioUtil
92118
return {};
93119
}
94120

95-
// 使用适当的缓冲区大小
96-
constexpr size_t BUFFER_FRAMES = 4096;
121+
// 使用较小的缓冲区以避免内存问题
122+
constexpr size_t BUFFER_FRAMES = 2048; // 减小缓冲区大小
97123
const size_t input_buffer_size = BUFFER_FRAMES * original_src_channels;
98-
const size_t output_buffer_size = static_cast<size_t>(BUFFER_FRAMES * ratio * original_src_channels) + 1024;
124+
const size_t output_buffer_size =
125+
static_cast<size_t>((static_cast<double>(BUFFER_FRAMES) * ratio * original_src_channels) + 1024);
99126

100-
std::vector<float> input_buffer(input_buffer_size);
127+
// 根据输入格式分配正确的输入缓冲区
128+
std::unique_ptr<float[]> float_input_buffer;
129+
std::unique_ptr<short[]> short_input_buffer;
130+
std::unique_ptr<int[]> int_input_buffer;
101131
std::vector<float> output_buffer(output_buffer_size);
102132

133+
void *input_buffer_ptr = nullptr;
134+
135+
if (is_float_input) {
136+
float_input_buffer = std::make_unique<float[]>(input_buffer_size);
137+
input_buffer_ptr = float_input_buffer.get();
138+
} else {
139+
// 检查位深度以决定输入缓冲区类型
140+
if (input_format == SF_FORMAT_PCM_16) {
141+
short_input_buffer = std::make_unique<short[]>(input_buffer_size);
142+
input_buffer_ptr = short_input_buffer.get();
143+
} else {
144+
// 对于24位和32位数据,都使用int缓冲区
145+
int_input_buffer = std::make_unique<int[]>(input_buffer_size);
146+
input_buffer_ptr = int_input_buffer.get();
147+
}
148+
}
149+
103150
sf_count_t total_input_frames = 0;
104151
sf_count_t total_output_frames = 0;
105152
bool processing_error = false;
106153

107154
while (!processing_error) {
108155
// 从源文件读取数据
109-
const sf_count_t frames_read = srcHandle.readf(input_buffer.data(), BUFFER_FRAMES);
156+
sf_count_t frames_read = 0;
157+
if (is_float_input) {
158+
frames_read = srcHandle.readf(static_cast<float *>(input_buffer_ptr), BUFFER_FRAMES);
159+
} else {
160+
if (input_format == SF_FORMAT_PCM_16) {
161+
frames_read = srcHandle.readf(static_cast<short *>(input_buffer_ptr), BUFFER_FRAMES);
162+
} else {
163+
// 对于24位和32位数据,使用read函数而非readf
164+
sf_count_t items_read =
165+
srcHandle.read(static_cast<int *>(input_buffer_ptr),
166+
static_cast<sf_count_t>(BUFFER_FRAMES * original_src_channels));
167+
frames_read = items_read / original_src_channels;
168+
}
169+
}
110170

111171
if (frames_read <= 0) {
112172
break;
@@ -115,7 +175,7 @@ namespace AudioUtil
115175
total_input_frames += frames_read;
116176

117177
// 计算这次读取的实际输入样本数(样本数 = 帧数 × 通道数)
118-
const size_t input_samples = frames_read * original_src_channels;
178+
const size_t input_samples = static_cast<size_t>(frames_read) * original_src_channels;
119179

120180
// 处理重采样
121181
size_t input_done_total = 0; // 跟踪本次读取的总处理量
@@ -130,8 +190,13 @@ namespace AudioUtil
130190
size_t input_done = 0;
131191
size_t output_done = 0;
132192

133-
error = soxr_process(resampler,
134-
input_buffer.data() + input_done_total, // 输入指针
193+
// 确保输入指针偏移正确
194+
void *current_input_ptr = static_cast<char *>(input_buffer_ptr) +
195+
(input_done_total *
196+
(is_float_input ? sizeof(float)
197+
: (input_format == SF_FORMAT_PCM_16 ? sizeof(short) : sizeof(int))));
198+
199+
error = soxr_process(resampler, current_input_ptr,
135200
input_to_process, // 输入样本数
136201
&input_done, // 实际处理的输入样本数
137202
output_buffer.data(), // 输出缓冲区
@@ -340,13 +405,13 @@ namespace AudioUtil
340405
}
341406

342407
// 创建输出WAV文件
343-
SndfileHandle outBuf(filepath.string(), SFM_WRITE, format, tar_channel, samplerate);
408+
SndfileHandle outBuf(filepath.string(), SFM_WRITE, (SF_FORMAT_WAV | SF_FORMAT_FLOAT), tar_channel, samplerate);
344409
if (!outBuf) {
345410
std::cerr << "Failed to open output WAV file: " << sf_strerror(nullptr) << std::endl;
346411
return false;
347412
}
348413

349-
constexpr size_t BUFFER_FRAMES = 4096;
414+
constexpr size_t BUFFER_FRAMES = 2048; // 减小缓冲区大小
350415
std::vector<float> buffer(BUFFER_FRAMES * channels);
351416
sf_count_t readFrames;
352417

0 commit comments

Comments
 (0)