Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial c #1

Merged
merged 18 commits into from
Jul 5, 2024
Prev Previous commit
Next Next commit
update
  • Loading branch information
albho committed Jul 4, 2024
commit 806b93a9c6f62779198a992d1925c6c80c5d4ec0
3 changes: 1 addition & 2 deletions demo/c/pv_speaker_demo.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,10 @@ int main(int argc, char *argv[]) {
char *pcmData = (char *) pcm;
for (int i = 0; i < num_samples; i += frame_length) {
bool is_last_frame = i + frame_length >= num_samples;
int32_t last_frame_length = num_samples - i;

status = pv_speaker_write(
speaker,
is_last_frame ? last_frame_length : frame_length,
is_last_frame ? num_samples - i : frame_length,
&pcmData[i * bits_per_sample / 8]);
if (status != PV_SPEAKER_STATUS_SUCCESS) {
fprintf(stderr, "Failed to write with %s.\n", pv_speaker_status_to_string(status));
Expand Down
8 changes: 4 additions & 4 deletions project/include/pv_circular_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include <stdint.h>

/**
* Forward declaration of pv_circular_buffer object. It handles reading and writing to a buffer.
* Forward declaration of pv_circular_buffer object. It handles reading and writing to a circular buffer.
*/
typedef struct pv_circular_buffer pv_circular_buffer_t;

Expand Down Expand Up @@ -55,9 +55,9 @@ void pv_circular_buffer_delete(pv_circular_buffer_t *object);
* Reads and copies the elements to the provided buffer.
*
* @param object Circular buffer object.
* @param buffer[out] A pointer to copy the elements into.
* @param buffer_length The amount to copy to read from the buffer.
* @param read_length[out] The total length of frames copied to buffer.
* @param buffer[out] A pointer to a pre-allocated buffer to receive the copied data.
* @param buffer_length The maximum number of elements that can be copied into `buffer`.
* @param read_length[out] Actual number of elements read.
* @return Status Code. Returns PV_CIRCULAR_BUFFER_STATUS_INVALID_ARGUMENT on failure.
*/
pv_circular_buffer_status_t pv_circular_buffer_read(
Expand Down
21 changes: 11 additions & 10 deletions project/src/pv_speaker.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
static const int32_t WRITE_RETRY_COUNT = 500;
static const int32_t WRITE_SLEEP_MILLI_SECONDS = 2;

static bool is_empty = false;
static bool is_stopped_and_empty = false;
static bool is_data_requested_while_empty = false;

struct pv_speaker {
Expand All @@ -48,17 +48,18 @@ static void pv_speaker_ma_callback(ma_device *device, void *output, const void *
pv_speaker_t *object = (pv_speaker_t *) device->pUserData;

ma_mutex_lock(&object->mutex);
int32_t read_length = 0;
pv_circular_buffer_read(object->buffer, output, (int32_t) frame_count, &read_length);
if (object->is_debug_logging_enabled) {
fprintf(stdout, "[INFO] Number of frames copied to output buffer: %d.\n", read_length);
}

// this callback being invoked after calling `pv_speaker_stop` and the circular buffer is empty indicates that all
// frames have been passed to the output buffer, and the device can stop without truncating the last frame of audio
if (is_empty) {
if (is_stopped_and_empty) {
is_data_requested_while_empty = true;
ma_mutex_unlock(&object->mutex);
return;
}

int32_t read_length = 0;
pv_circular_buffer_read(object->buffer, output, (int32_t) frame_count, &read_length);

ma_mutex_unlock(&object->mutex);
}

Expand Down Expand Up @@ -220,7 +221,7 @@ PV_API pv_speaker_status_t pv_speaker_start(pv_speaker_t *object) {
return PV_SPEAKER_STATUS_INVALID_ARGUMENT;
}

is_empty = false;
is_stopped_and_empty = false;
is_data_requested_while_empty = false;

ma_result result = ma_device_start(&(object->device));
Expand All @@ -244,12 +245,12 @@ PV_API pv_speaker_status_t pv_speaker_stop(pv_speaker_t *object) {
}

// waits for all frames to be copied to output buffer before stopping
while (!is_empty || !is_data_requested_while_empty) {
while (!is_stopped_and_empty || !is_data_requested_while_empty) {
ma_mutex_lock(&object->mutex);
int32_t count = 0;
pv_circular_buffer_status_t status = pv_circular_buffer_get_count(object->buffer, &count);
if (status == PV_CIRCULAR_BUFFER_STATUS_SUCCESS && count == 0) {
is_empty = true;
is_stopped_and_empty = true;
} else if (status != PV_CIRCULAR_BUFFER_STATUS_SUCCESS) {
ma_mutex_unlock(&object->mutex);
return PV_SPEAKER_STATUS_RUNTIME_ERROR;
Expand Down
Loading