Skip to content

Commit 0affd19

Browse files
authored
Fix C API for reading multi-channel wave files (#3430)
1 parent b0c562c commit 0affd19

2 files changed

Lines changed: 31 additions & 38 deletions

File tree

sherpa-onnx/c-api/c-api.cc

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ static sherpa_onnx::OfflineRecognizerConfig GetOfflineRecognizerConfig(
581581

582582
recognizer_config.model_config.fire_red_asr_ctc.model =
583583
SHERPA_ONNX_OR(config->model_config.fire_red_asr_ctc.model, "");
584-
584+
585585
recognizer_config.model_config.qwen3_asr.conv_frontend =
586586
SHERPA_ONNX_OR(config->model_config.qwen3_asr.conv_frontend, "");
587587
recognizer_config.model_config.qwen3_asr.encoder =
@@ -2026,60 +2026,51 @@ void SherpaOnnxFreeWave(const SherpaOnnxWave *wave) {
20262026
}
20272027
}
20282028

2029-
struct SherpaOnnxMultiChannelWaveImpl {
2030-
std::vector<std::vector<float>> samples;
2031-
};
2032-
2033-
// Internal wrapper that pairs the public C struct with its C++ implementation
2034-
// so that SherpaOnnxFreeMultiChannelWave can recover the impl pointer.
2035-
struct SherpaOnnxMultiChannelWaveInternal {
2036-
SherpaOnnxMultiChannelWave pub;
2037-
SherpaOnnxMultiChannelWaveImpl *impl;
2029+
struct SherpaOnnxMultiChannelWaveInternal : SherpaOnnxMultiChannelWave {
2030+
std::vector<float> flat_samples;
2031+
std::vector<const float *> channel_ptrs;
20382032
};
20392033

20402034
const SherpaOnnxMultiChannelWave *SherpaOnnxReadWaveMultiChannel(
20412035
const char *filename) {
20422036
int32_t sample_rate = -1;
20432037
bool is_ok = false;
2044-
auto samples =
2038+
2039+
auto samples_2d =
20452040
sherpa_onnx::ReadWaveMultiChannel(filename, &sample_rate, &is_ok);
2046-
if (!is_ok || samples.empty()) {
2041+
2042+
if (!is_ok || samples_2d.empty()) {
20472043
return nullptr;
20482044
}
20492045

2050-
int32_t num_channels = samples.size();
2051-
int32_t num_samples = samples[0].size();
2046+
int32_t num_channels = static_cast<int32_t>(samples_2d.size());
2047+
int32_t num_samples = static_cast<int32_t>(samples_2d[0].size());
20522048

2053-
// Allocate the internal storage that owns the data.
2054-
auto *impl = new SherpaOnnxMultiChannelWaveImpl;
2055-
impl->samples = std::move(samples);
2049+
auto *w = new SherpaOnnxMultiChannelWaveInternal();
20562050

2057-
// Allocate the arrays of pointers visible to the C caller.
2058-
const float **channel_ptrs = new const float *[num_channels];
2059-
for (int32_t c = 0; c < num_channels; ++c) {
2060-
channel_ptrs[c] = impl->samples[c].data();
2051+
w->flat_samples.reserve(num_channels * num_samples);
2052+
for (const auto &channel : samples_2d) {
2053+
w->flat_samples.insert(w->flat_samples.end(), channel.begin(),
2054+
channel.end());
20612055
}
20622056

2063-
// Pack everything into the public struct.
2064-
auto *w = new SherpaOnnxMultiChannelWaveInternal;
2065-
w->pub.samples = channel_ptrs;
2066-
w->pub.num_channels = num_channels;
2067-
w->pub.num_samples = num_samples;
2068-
w->pub.sample_rate = sample_rate;
2069-
w->impl = impl;
2057+
w->channel_ptrs.resize(num_channels);
2058+
for (int32_t c = 0; c != num_channels; ++c) {
2059+
w->channel_ptrs[c] = w->flat_samples.data() + (c * num_samples);
2060+
}
2061+
2062+
w->samples = w->channel_ptrs.data();
2063+
w->num_channels = num_channels;
2064+
w->num_samples = num_samples;
2065+
w->sample_rate = sample_rate;
20702066

2071-
return &w->pub;
2067+
return w;
20722068
}
20732069

20742070
void SherpaOnnxFreeMultiChannelWave(const SherpaOnnxMultiChannelWave *wave) {
2075-
if (!wave) return;
2076-
// The SherpaOnnxMultiChannelWave is the first member of
2077-
// SherpaOnnxMultiChannelWaveInternal, so the pointer values are identical.
2078-
auto *iw = reinterpret_cast<SherpaOnnxMultiChannelWaveInternal *>(
2079-
const_cast<SherpaOnnxMultiChannelWave *>(wave));
2080-
delete[] iw->pub.samples;
2081-
delete iw->impl;
2082-
delete iw;
2071+
if (wave) {
2072+
delete static_cast<const SherpaOnnxMultiChannelWaveInternal *>(wave);
2073+
}
20832074
}
20842075

20852076
struct SherpaOnnxSpokenLanguageIdentification {

sherpa-onnx/c-api/c-api.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2829,7 +2829,9 @@ SHERPA_ONNX_API void SherpaOnnxFreeWave(const SherpaOnnxWave *wave);
28292829
* Free this object with SherpaOnnxFreeMultiChannelWave().
28302830
*/
28312831
typedef struct SherpaOnnxMultiChannelWave {
2832-
/** samples[c] points to channel c samples normalized to [-1, 1]. */
2832+
/** samples[c] points to channel c samples normalized to [-1, 1].
2833+
* Note that samples[c] and samples[c+1] are contiguous in memory.
2834+
* */
28332835
const float *const *samples;
28342836
/** Number of channels. */
28352837
int32_t num_channels;

0 commit comments

Comments
 (0)