Skip to content

Commit 613e808

Browse files
mtdxccqm
andauthored
move portaudio common record code to microphone (#2264)
Co-authored-by: cqm <cqm@97kid.com>
1 parent 921f0f4 commit 613e808

12 files changed

Lines changed: 130 additions & 446 deletions

cxx-api-examples/parakeet-tdt-simulate-streaming-microphone-cxx-api.cc

Lines changed: 6 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -116,47 +116,31 @@ int32_t main() {
116116
sherpa_onnx::Microphone mic;
117117

118118
PaDeviceIndex num_devices = Pa_GetDeviceCount();
119-
std::cout << "Num devices: " << num_devices << "\n";
120119
if (num_devices == 0) {
121120
std::cerr << " If you are using Linux, please try "
122121
"./build/bin/sense-voice-simulate-streaming-alsa-cxx-api\n";
123122
return -1;
124123
}
125124

126125
int32_t device_index = Pa_GetDefaultInputDevice();
127-
128126
const char *pDeviceIndex = std::getenv("SHERPA_ONNX_MIC_DEVICE");
129127
if (pDeviceIndex) {
130128
fprintf(stderr, "Use specified device: %s\n", pDeviceIndex);
131129
device_index = atoi(pDeviceIndex);
132130
}
131+
mic.PrintDevices(device_index);
133132

134-
for (int32_t i = 0; i != num_devices; ++i) {
135-
const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
136-
fprintf(stderr, " %s %d %s\n", (i == device_index) ? "*" : " ", i,
137-
info->name);
138-
}
139-
140-
PaStreamParameters param;
141-
param.device = device_index;
142-
143-
fprintf(stderr, "Use device: %d\n", param.device);
144-
145-
const PaDeviceInfo *info = Pa_GetDeviceInfo(param.device);
146-
fprintf(stderr, " Name: %s\n", info->name);
147-
fprintf(stderr, " Max input channels: %d\n", info->maxInputChannels);
148-
149-
param.channelCount = 1;
150-
param.sampleFormat = paFloat32;
151-
152-
param.suggestedLatency = info->defaultLowInputLatency;
153-
param.hostApiSpecificStreamInfo = nullptr;
154133
float mic_sample_rate = 16000;
155134
const char *sample_rate_str = std::getenv("SHERPA_ONNX_MIC_SAMPLE_RATE");
156135
if (sample_rate_str) {
157136
fprintf(stderr, "Use sample rate %f for mic\n", mic_sample_rate);
158137
mic_sample_rate = atof(sample_rate_str);
159138
}
139+
if(!mic.OpenDevice(device_index, mic_sample_rate, 1, RecordCallback,
140+
nullptr) == false) {
141+
std::cerr << "Failed to open microphone device\n";
142+
return -1;
143+
}
160144
float sample_rate = 16000;
161145
LinearResampler resampler;
162146
if (mic_sample_rate != sample_rate) {
@@ -168,27 +152,6 @@ int32_t main() {
168152
lowpass_cutoff, lowpass_filter_width);
169153
}
170154

171-
PaStream *stream;
172-
PaError err =
173-
Pa_OpenStream(&stream, &param, nullptr, /* &outputParameters, */
174-
mic_sample_rate,
175-
0, // frames per buffer
176-
paClipOff, // we won't output out of range samples
177-
// so don't bother clipping them
178-
RecordCallback, // RecordCallback is run in a separate
179-
// thread created by portaudio
180-
nullptr);
181-
if (err != paNoError) {
182-
fprintf(stderr, "portaudio error: %s\n", Pa_GetErrorText(err));
183-
exit(EXIT_FAILURE);
184-
}
185-
186-
err = Pa_StartStream(stream);
187-
if (err != paNoError) {
188-
fprintf(stderr, "portaudio error: %s\n", Pa_GetErrorText(err));
189-
exit(EXIT_FAILURE);
190-
}
191-
192155
int32_t window_size = 512; // samples, please don't change
193156

194157
int32_t offset = 0;
@@ -276,11 +239,5 @@ int32_t main() {
276239
}
277240
}
278241

279-
err = Pa_CloseStream(stream);
280-
if (err != paNoError) {
281-
fprintf(stderr, "portaudio error: %s\n", Pa_GetErrorText(err));
282-
exit(EXIT_FAILURE);
283-
}
284-
285242
return 0;
286243
}

cxx-api-examples/sense-voice-simulate-streaming-microphone-cxx-api.cc

Lines changed: 5 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -112,41 +112,20 @@ int32_t main() {
112112
sherpa_onnx::Microphone mic;
113113

114114
PaDeviceIndex num_devices = Pa_GetDeviceCount();
115-
std::cout << "Num devices: " << num_devices << "\n";
116115
if (num_devices == 0) {
117116
std::cerr << " If you are using Linux, please try "
118117
"./build/bin/sense-voice-simulate-streaming-alsa-cxx-api\n";
119118
return -1;
120119
}
121120

122121
int32_t device_index = Pa_GetDefaultInputDevice();
123-
124122
const char *pDeviceIndex = std::getenv("SHERPA_ONNX_MIC_DEVICE");
125123
if (pDeviceIndex) {
126124
fprintf(stderr, "Use specified device: %s\n", pDeviceIndex);
127125
device_index = atoi(pDeviceIndex);
128126
}
127+
mic.PrintDevices(device_index);
129128

130-
for (int32_t i = 0; i != num_devices; ++i) {
131-
const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
132-
fprintf(stderr, " %s %d %s\n", (i == device_index) ? "*" : " ", i,
133-
info->name);
134-
}
135-
136-
PaStreamParameters param;
137-
param.device = device_index;
138-
139-
fprintf(stderr, "Use device: %d\n", param.device);
140-
141-
const PaDeviceInfo *info = Pa_GetDeviceInfo(param.device);
142-
fprintf(stderr, " Name: %s\n", info->name);
143-
fprintf(stderr, " Max input channels: %d\n", info->maxInputChannels);
144-
145-
param.channelCount = 1;
146-
param.sampleFormat = paFloat32;
147-
148-
param.suggestedLatency = info->defaultLowInputLatency;
149-
param.hostApiSpecificStreamInfo = nullptr;
150129
float mic_sample_rate = 16000;
151130
const char *sample_rate_str = std::getenv("SHERPA_ONNX_MIC_SAMPLE_RATE");
152131
if (sample_rate_str) {
@@ -163,26 +142,10 @@ int32_t main() {
163142
resampler = LinearResampler::Create(mic_sample_rate, sample_rate,
164143
lowpass_cutoff, lowpass_filter_width);
165144
}
166-
167-
PaStream *stream;
168-
PaError err =
169-
Pa_OpenStream(&stream, &param, nullptr, /* &outputParameters, */
170-
mic_sample_rate,
171-
0, // frames per buffer
172-
paClipOff, // we won't output out of range samples
173-
// so don't bother clipping them
174-
RecordCallback, // RecordCallback is run in a separate
175-
// thread created by portaudio
176-
nullptr);
177-
if (err != paNoError) {
178-
fprintf(stderr, "portaudio error: %s\n", Pa_GetErrorText(err));
179-
exit(EXIT_FAILURE);
180-
}
181-
182-
err = Pa_StartStream(stream);
183-
if (err != paNoError) {
184-
fprintf(stderr, "portaudio error: %s\n", Pa_GetErrorText(err));
185-
exit(EXIT_FAILURE);
145+
if (mic.OpenDevice(device_index, mic_sample_rate, 1, RecordCallback,
146+
nullptr) == false) {
147+
std::cerr << "Failed to open microphone device\n";
148+
return -1;
186149
}
187150

188151
int32_t window_size = 512; // samples, please don't change
@@ -272,11 +235,5 @@ int32_t main() {
272235
}
273236
}
274237

275-
err = Pa_CloseStream(stream);
276-
if (err != paNoError) {
277-
fprintf(stderr, "portaudio error: %s\n", Pa_GetErrorText(err));
278-
exit(EXIT_FAILURE);
279-
}
280-
281238
return 0;
282239
}

sherpa-onnx/csrc/microphone.cc

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
#include <stdio.h>
88
#include <stdlib.h>
99

10-
#include "portaudio.h" // NOLINT
11-
1210
namespace sherpa_onnx {
1311

1412
Microphone::Microphone() {
@@ -20,10 +18,85 @@ Microphone::Microphone() {
2018
}
2119

2220
Microphone::~Microphone() {
21+
CloseDevice();
2322
PaError err = Pa_Terminate();
2423
if (err != paNoError) {
2524
fprintf(stderr, "portaudio error: %s\n", Pa_GetErrorText(err));
26-
exit(-1);
25+
}
26+
}
27+
28+
int Microphone::GetDeviceCount() const {
29+
return Pa_GetDeviceCount();
30+
}
31+
32+
int Microphone::GetDefaultInputDevice() const {
33+
return Pa_GetDefaultInputDevice();
34+
}
35+
36+
void Microphone::PrintDevices(int device_index) const {
37+
PaDeviceIndex num_devices = Pa_GetDeviceCount();
38+
fprintf(stderr, "Num devices: %d\n", num_devices);
39+
for (int32_t i = 0; i != num_devices; ++i) {
40+
const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
41+
fprintf(stderr, " %s %d %s\n", (i == device_index) ? "*" : " ", i,
42+
info->name);
43+
}
44+
}
45+
46+
bool Microphone::OpenDevice(int index, int sample_rate, int channel, PaStreamCallback cb, void* userdata) {
47+
if (index < 0 || index >= Pa_GetDeviceCount()) {
48+
fprintf(stderr, "Invalid device index: %d\n", index);
49+
return false;
50+
}
51+
52+
const PaDeviceInfo *info = Pa_GetDeviceInfo(index);
53+
if (!info) {
54+
fprintf(stderr, "No device info found for index: %d\n", index);
55+
return false;
56+
}
57+
58+
CloseDevice();
59+
60+
fprintf(stderr, "Use device: %d\n", index);
61+
fprintf(stderr, " Name: %s\n", info->name);
62+
fprintf(stderr, " Max input channels: %d\n", info->maxInputChannels);
63+
64+
PaStreamParameters param;
65+
param.device = index;
66+
param.channelCount = channel;
67+
param.sampleFormat = paFloat32;
68+
param.suggestedLatency = info->defaultLowInputLatency;
69+
param.hostApiSpecificStreamInfo = nullptr;
70+
71+
PaError err = Pa_OpenStream(&stream, &param, nullptr, /* &outputParameters, */
72+
sample_rate,
73+
0, // frames per buffer
74+
paClipOff, // we won't output out of range samples
75+
// so don't bother clipping them
76+
cb, userdata);
77+
if (err != paNoError) {
78+
fprintf(stderr, "portaudio error: %s\n", Pa_GetErrorText(err));
79+
return false;
80+
}
81+
82+
err = Pa_StartStream(stream);
83+
fprintf(stderr, "Started\n");
84+
85+
if (err != paNoError) {
86+
fprintf(stderr, "portaudio error: %s\n", Pa_GetErrorText(err));
87+
CloseDevice();
88+
return false;
89+
}
90+
return true;
91+
}
92+
93+
void Microphone::CloseDevice() {
94+
if (stream) {
95+
PaError err = Pa_CloseStream(stream);
96+
if (err != paNoError) {
97+
fprintf(stderr, "Pa_CloseStream error: %s\n", Pa_GetErrorText(err));
98+
}
99+
stream = nullptr;
27100
}
28101
}
29102

sherpa-onnx/csrc/microphone.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,22 @@
44

55
#ifndef SHERPA_ONNX_CSRC_MICROPHONE_H_
66
#define SHERPA_ONNX_CSRC_MICROPHONE_H_
7+
#include "portaudio.h" // NOLINT
78

89
namespace sherpa_onnx {
910

1011
class Microphone {
12+
PaStream *stream = nullptr;
1113
public:
1214
Microphone();
1315
~Microphone();
16+
17+
int GetDeviceCount() const;
18+
int GetDefaultInputDevice() const;
19+
void PrintDevices(int sel) const;
20+
21+
bool OpenDevice(int index, int sample_rate, int channel, PaStreamCallback cb, void* userdata);
22+
void CloseDevice();
1423
};
1524

1625
} // namespace sherpa_onnx

sherpa-onnx/csrc/sherpa-onnx-alsa-offline-speaker-identification.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
#include "sherpa-onnx/csrc/alsa.h"
1616
#include "sherpa-onnx/csrc/macros.h"
17-
#include "sherpa-onnx/csrc/microphone.h"
1817
#include "sherpa-onnx/csrc/speaker-embedding-extractor.h"
1918
#include "sherpa-onnx/csrc/speaker-embedding-manager.h"
2019
#include "sherpa-onnx/csrc/wave-reader.h"

sherpa-onnx/csrc/sherpa-onnx-keyword-spotter-microphone.cc

Lines changed: 4 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,7 @@ for a list of pre-trained models to download.
7979

8080
sherpa_onnx::Microphone mic;
8181

82-
PaDeviceIndex num_devices = Pa_GetDeviceCount();
83-
fprintf(stderr, "Num devices: %d\n", num_devices);
84-
8582
int32_t device_index = Pa_GetDefaultInputDevice();
86-
8783
if (device_index == paNoDevice) {
8884
fprintf(stderr, "No default input device found\n");
8985
fprintf(stderr, "If you are using Linux, please switch to \n");
@@ -97,51 +93,17 @@ for a list of pre-trained models to download.
9793
device_index = atoi(pDeviceIndex);
9894
}
9995

100-
for (int32_t i = 0; i != num_devices; ++i) {
101-
const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
102-
fprintf(stderr, " %s %d %s\n", (i == device_index) ? "*" : " ", i,
103-
info->name);
104-
}
105-
106-
PaStreamParameters param;
107-
param.device = device_index;
108-
109-
fprintf(stderr, "Use device: %d\n", param.device);
110-
111-
const PaDeviceInfo *info = Pa_GetDeviceInfo(param.device);
112-
fprintf(stderr, " Name: %s\n", info->name);
113-
fprintf(stderr, " Max input channels: %d\n", info->maxInputChannels);
114-
115-
param.channelCount = 1;
116-
param.sampleFormat = paFloat32;
117-
118-
param.suggestedLatency = info->defaultLowInputLatency;
119-
param.hostApiSpecificStreamInfo = nullptr;
96+
mic.PrintDevices(device_index);
12097

12198
const char *pSampleRateStr = std::getenv("SHERPA_ONNX_MIC_SAMPLE_RATE");
12299
if (pSampleRateStr) {
123100
fprintf(stderr, "Use sample rate %f for mic\n", mic_sample_rate);
124101
mic_sample_rate = atof(pSampleRateStr);
125102
}
126103

127-
PaStream *stream;
128-
PaError err =
129-
Pa_OpenStream(&stream, &param, nullptr, /* &outputParameters, */
130-
mic_sample_rate,
131-
0, // frames per buffer
132-
paClipOff, // we won't output out of range samples
133-
// so don't bother clipping them
134-
RecordCallback, s.get());
135-
if (err != paNoError) {
136-
fprintf(stderr, "portaudio error: %s\n", Pa_GetErrorText(err));
137-
exit(EXIT_FAILURE);
138-
}
139-
140-
err = Pa_StartStream(stream);
141-
fprintf(stderr, "Started\n");
142-
143-
if (err != paNoError) {
144-
fprintf(stderr, "portaudio error: %s\n", Pa_GetErrorText(err));
104+
if(!mic.OpenDevice(device_index, mic_sample_rate, 1,
105+
RecordCallback, s.get())) {
106+
fprintf(stderr, "portaudio error: %d\n", device_index);
145107
exit(EXIT_FAILURE);
146108
}
147109

@@ -164,11 +126,5 @@ for a list of pre-trained models to download.
164126
Pa_Sleep(20); // sleep for 20ms
165127
}
166128

167-
err = Pa_CloseStream(stream);
168-
if (err != paNoError) {
169-
fprintf(stderr, "portaudio error: %s\n", Pa_GetErrorText(err));
170-
exit(EXIT_FAILURE);
171-
}
172-
173129
return 0;
174130
}

0 commit comments

Comments
 (0)