Skip to content

Commit

Permalink
* optimize audio
Browse files Browse the repository at this point in the history
  • Loading branch information
lxowalle committed Dec 24, 2024
1 parent 8d9f4d5 commit b81bfc8
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 20 deletions.
28 changes: 28 additions & 0 deletions components/voice/include/maix_audio.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ namespace maix::audio
*/
bool mute(int data = -1);

/**
* Reset record status
* @param start start prepare audio data, default is True
* @maixpy maix.audio.Recorder.reset
*/
void reset(bool start = true);

/**
* Record, Read all cached data in buffer and return. If there is no audio data in the buffer, may return empty data.
* @param record_ms Block and record audio data lasting `record_ms` milliseconds and save it to a file, the return value does not return audio data. Only valid if the initialisation `path` is set.
Expand All @@ -105,6 +112,20 @@ namespace maix::audio
*/
err::Err finish();

/**
* Get bytes per frame
* @return bytes per frame
* @maixpy maix.audio.Recorder.frame_size
*/
int frame_size();

/**
* Get remaining readable bytes
* @return remain size
* @maixpy maix.audio.Recorder.remain_size
*/
int remain_size();

/**
* Get sample rate
* @return returns sample rate
Expand Down Expand Up @@ -181,6 +202,13 @@ namespace maix::audio
*/
err::Err play(maix::Bytes *data = maix::audio::Player::NoneBytes);

/**
* Get bytes per frame
* @return bytes per frame
* @maixpy maix.audio.Player.frame_size
*/
int frame_size();

/**
* Get sample rate
* @return returns sample rate
Expand Down
76 changes: 62 additions & 14 deletions components/voice/port/maixcam/maix_audio_mmf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,14 @@ namespace maix::audio
return audio::Format::FMT_NONE;
}

void Recorder::reset(bool start) {
snd_pcm_t *handle = (snd_pcm_t *)_handle;
snd_pcm_prepare(handle);
if (start) {
snd_pcm_start(handle);
}
}

maix::Bytes *Recorder::record(int record_ms) {
snd_pcm_t *handle = (snd_pcm_t *)_handle;
void *buffer = _buffer;
Expand Down Expand Up @@ -593,26 +601,49 @@ namespace maix::audio
}
}

auto state = snd_pcm_state(handle);
if (state != SND_PCM_STATE_RUNNING) {
snd_pcm_start(handle);
}

if (record_ms > 0) {
uint64_t start_ms = time::ticks_ms();
if (_path.size() <= 0) {
log::error("If you pass in the record_ms parameter, you must also set the correct path in audio::Audio()\r\n");
return new Bytes();
auto bytes_per_frame = this->frame_size();
auto period_size = bytes_per_frame * _period_size;
auto read_remain_size = record_ms * _sample_rate * bytes_per_frame / 1000;
auto period_ms = period_size * 1000 / _sample_rate / bytes_per_frame;

if (read_remain_size < period_size) {
auto err_msg = "the record time must be greater than " + std::to_string(period_ms) + " ms";
err::check_raise(err::ERR_ARGS, err_msg);
}

while (time::ticks_ms() - start_ms <= (uint64_t)record_ms) {
len = 0;
while (len >= 0) {
len = _alsa_capture_pop(handle, format, channel, _period_size, buffer, buffer_size);
if (len > 0) {
if (_file)
fwrite(buffer, 1, len, _file);
}
auto out_bytes = new Bytes(nullptr, read_remain_size);
err::check_null_raise(out_bytes, "Create new bytes failed!");
while (read_remain_size > 0 && !app::need_exit()) {
if (this->remain_size() < period_size) {
time::sleep_ms(1);
continue;
}
time::sleep_ms(10);

auto buffer_size = read_remain_size;
auto buffer = out_bytes->data + out_bytes->data_len - read_remain_size;

auto len = (int)snd_pcm_readi(handle, buffer, buffer_size / bytes_per_frame);
if (len == -EPIPE) {
snd_pcm_prepare(handle);
} else if (len < 0) {
log::error("pcm read error: %s", snd_strerror(len));
return new Bytes();
} else {
read_remain_size -= len * bytes_per_frame;
}
// log::info("pcm read total %d, remain %d len %d", out_bytes->data_len, read_remain_size, len * bytes_per_frame);
}

return new Bytes();
if (_file)
fwrite(out_bytes->data, 1, out_bytes->data_len, _file);

return out_bytes;
} else {
int add_len = 4096;
int valid_len = 0;
Expand Down Expand Up @@ -647,6 +678,17 @@ namespace maix::audio
return new Bytes();
}

int Recorder::frame_size() {
snd_pcm_format_t format = _alsa_format_from_maix(_format);
int format_width = snd_pcm_format_width(format) / 8;
return format_width * _channel;
}

int Recorder::remain_size() {
snd_pcm_t *handle = (snd_pcm_t *)_handle;
return snd_pcm_avail_update(handle);
}

maix::Bytes *Recorder::record_bytes(int record_size) {
snd_pcm_t *handle = (snd_pcm_t *)_handle;
void *buffer = _buffer;
Expand Down Expand Up @@ -899,4 +941,10 @@ namespace maix::audio

return ret;
}

int Player::frame_size() {
snd_pcm_format_t format = _alsa_format_from_maix(_format);
int format_width = snd_pcm_format_width(format) / 8;
return format_width * _channel;
}
} // namespace maix::audio
15 changes: 9 additions & 6 deletions examples/audio_demo/main/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ static void helper(void)
log::info(
"==================================\r\n"
"Please input command:\r\n"
"0 [path] [record_ms] [sample_rate] [channel] [format]: record block, ./audio_demo 0 output.pcm 3\r\n"
"0 [path] [ms_per_record] [sample_rate] [channel] [format]: record block, ./audio_demo 0 output.pcm 30\r\n"
"1 [path] [sample_rate] [channel] [format]: record nonblock, ./audio_demo 1 output.pcm 48000 1 2\r\n"
"2 [volumn]: set recorder volume, ./audio_demo 2 12\r\n"
"3 [path] [sample_rate] [channel] [format]: playback block, ./audio_demo 3 output.pcm\r\n"
Expand Down Expand Up @@ -201,11 +201,11 @@ int _main(int argc, char* argv[])
switch (cmd) {
case 0:
{
std::string path = "output.pcm";
int sample_rate = 48000, channel = 1, record_ms = 3000;
std::string path = "output.wav";
int sample_rate = 48000, channel = 1, record_ms = 50;
audio::Format format = audio::Format::FMT_S16_LE;
if (argc > 2) path = argv[2];
if (argc > 3) record_ms = atoi(argv[3]) * 1000;
if (argc > 3) record_ms = atoi(argv[3]);
if (argc > 4) sample_rate = atoi(argv[4]);
if (argc > 5) channel = atoi(argv[5]);
if (argc > 6) {
Expand All @@ -221,11 +221,14 @@ int _main(int argc, char* argv[])

log::info("Ready to record %ld ms, and save to %s\r\n", record_ms, path.c_str());
audio::Recorder r = audio::Recorder(path, sample_rate, format, channel);
r.record(record_ms);
r.volume(100);
r.reset();

log::info("Record over!\r\n");
while (!app::need_exit()) {
time::sleep_ms(1000);
auto t = time::ticks_ms();
auto data = r.record(record_ms);
log::info("Record %ld ms, bytes:%d, used %lld ", record_ms, data->size(), time::ticks_ms() - t);
}
break;
}
Expand Down

0 comments on commit b81bfc8

Please sign in to comment.