Skip to content

Commit d332bf9

Browse files
authored
v3.0 c (#91)
1 parent 0a617f0 commit d332bf9

File tree

9 files changed

+338
-38
lines changed

9 files changed

+338
-38
lines changed

.github/workflows/c-demos.yml

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737

3838
strategy:
3939
matrix:
40-
os: [ubuntu-latest, windows-latest, macos-latest]
40+
os: [ ubuntu-latest, windows-latest, macos-latest ]
4141
include:
4242
- os: ubuntu-latest
4343
pv_recorder_platform: "linux"
@@ -62,7 +62,7 @@ jobs:
6262

6363
strategy:
6464
matrix:
65-
machine: [rpi3-32, rpi3-64, rpi4-32, rpi4-64, rpi5-64, pv-windows-arm64]
65+
machine: [ rpi3-32, rpi3-64, rpi4-32, rpi4-64, rpi5-64, pv-windows-arm64 ]
6666
include:
6767
- machine: rpi3-32
6868
make_file: "Unix Makefiles"
@@ -99,7 +99,8 @@ jobs:
9999

100100
strategy:
101101
matrix:
102-
os: [ubuntu-latest, windows-latest, macos-latest]
102+
device: [ cpu, cpu:1 ]
103+
os: [ ubuntu-latest, windows-latest, macos-latest ]
103104
include:
104105
- os: ubuntu-latest
105106
platform: linux
@@ -131,14 +132,15 @@ jobs:
131132
run: cmake --build ./build --target koala_demo_file
132133

133134
- name: Test
134-
run: python test/test_koala_c.py ${{secrets.PV_VALID_ACCESS_KEY}} ${{ matrix.platform }} ${{ matrix.arch }}
135+
run: python test/test_koala_c.py ${{secrets.PV_VALID_ACCESS_KEY}} ${{ matrix.device }} ${{ matrix.platform }} ${{ matrix.arch }}
135136

136137
build-filedemo-self-hosted:
137138
runs-on: ${{ matrix.machine }}
138139

139140
strategy:
140141
matrix:
141-
machine: [rpi3-32, rpi3-64, rpi4-32, rpi4-64, rpi5-64]
142+
device: [ best ]
143+
machine: [ rpi3-32, rpi3-64, rpi4-32, rpi4-64, rpi5-64, pv-windows-arm64 ]
142144
include:
143145
- machine: rpi3-32
144146
platform: raspberry-pi
@@ -170,6 +172,24 @@ jobs:
170172
arch: arm64
171173
make_file: "MinGW Makefiles"
172174
pv_recorder_platform: "windows-arm64"
175+
- device: gpu
176+
machine: pv-linux
177+
platform: linux
178+
arch: x86_64
179+
make_file: "Unix Makefiles"
180+
pv_recorder_platform: "linux"
181+
- device: gpu
182+
machine: pv-windows
183+
platform: windows
184+
arch: amd64
185+
make_file: "MinGW Makefiles"
186+
pv_recorder_platform: "windows-amd64"
187+
- device: gpu
188+
machine: pv-ios
189+
platform: mac
190+
arch: arm64
191+
make_file: "Unix Makefiles"
192+
pv_recorder_platform: "mac-arm64"
173193

174194
steps:
175195
- uses: actions/checkout@v3
@@ -183,4 +203,4 @@ jobs:
183203
run: cmake --build ./build --target koala_demo_file
184204

185205
- name: Test
186-
run: python test/test_koala_c.py ${{secrets.PV_VALID_ACCESS_KEY}} ${{ matrix.platform }} ${{ matrix.arch }}
206+
run: python3 test/test_koala_c.py ${{secrets.PV_VALID_ACCESS_KEY}} ${{ matrix.device }} ${{ matrix.platform }} ${{ matrix.arch }}

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,9 @@ When done be sure to explicitly release the resources using `koala.delete()`.
243243
```c
244244
pv_koala_t *handle = NULL;
245245
const char *model_path = "${MODEL_PATH}";
246-
pv_status_t status = pv_koala_init(${ACCESS_KEY}, model_path, &handle);
246+
const char *device = "best";
247+
248+
pv_status_t status = pv_koala_init(${ACCESS_KEY}, model_path, device, &handle);
247249
if (status != PV_STATUS_SUCCESS) {
248250
// error handling logic
249251
}
@@ -320,6 +322,13 @@ Replace `${ACCESS_KEY}` with yours obtained from [Picovoice Console](https://con
320322

321323
## Releases
322324

325+
### v3.0.0 - December 9th, 2025
326+
327+
- Improved engine performance
328+
- Added support for running on GPU or multiple CPU cores
329+
- Node.js min version bumped to Node 18
330+
- iOS min version bumped to iOS 16
331+
323332
### v2.0.0 - November 24th, 2023
324333

325334
- Improvements to error reporting

demo/c/koala_demo_file.c

Lines changed: 115 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
/*
2-
Copyright 2023 Picovoice Inc.
2+
Copyright 2023-2025 Picovoice Inc.
33
44
You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
55
file accompanying this source.
6-
6+
77
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
88
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
99
specific language governing permissions and limitations under the License.
1010
*/
1111

1212
#include <getopt.h>
1313
#include <math.h>
14+
#include <stdbool.h>
1415
#include <stdio.h>
1516
#include <stdlib.h>
1617
#include <sys/time.h>
@@ -87,17 +88,21 @@ static void print_dl_error(const char *message) {
8788
}
8889

8990
static struct option long_options[] = {
90-
{"access_key", required_argument, NULL, 'a'},
91-
{"library_path", required_argument, NULL, 'l'},
92-
{"model_path", required_argument, NULL, 'm'},
93-
{"input_path", required_argument, NULL, 'i'},
94-
{"output_path", required_argument, NULL, 'o'},
91+
{"access_key", required_argument, NULL, 'a'},
92+
{"library_path", required_argument, NULL, 'l'},
93+
{"model_path", required_argument, NULL, 'm'},
94+
{"device", required_argument, NULL, 'y'},
95+
{"input_path", required_argument, NULL, 'i'},
96+
{"output_path", required_argument, NULL, 'o'},
97+
{"show_inference_devices", required_argument, NULL, 'z'},
9598
};
9699

97100
static void print_usage(const char *program_name) {
98101
fprintf(
99102
stdout,
100-
"Usage: %s [-l LIBRARY_PATH -m MODEL_PATH -a ACCESS_KEY -i INPUT_PATH -o OUTPUT_PATH]\n",
103+
"Usage: %s -l LIBRARY_PATH [-m MODEL_PATH -a ACCESS_KEY -y DEVICE -i INPUT_PATH -o OUTPUT_PATH]\n"
104+
" %s [-z, --show_inference_devices] -l LIBRARY_PATH\n",
105+
program_name,
101106
program_name);
102107
}
103108

@@ -122,16 +127,94 @@ static void print_progress_bar(size_t num_total_samples, size_t num_processed_sa
122127
fflush(stdout);
123128
}
124129

130+
static void print_inference_devices(const char *library_path) {
131+
void *dl_handle = open_dl(library_path);
132+
if (!dl_handle) {
133+
fprintf(stderr, "Failed to open library at '%s'.\n", library_path);
134+
exit(EXIT_FAILURE);
135+
}
136+
137+
const char *(*pv_status_to_string_func)(pv_status_t) = load_symbol(dl_handle, "pv_status_to_string");
138+
if (!pv_status_to_string_func) {
139+
print_dl_error("Failed to load 'pv_status_to_string'");
140+
exit(EXIT_FAILURE);
141+
}
142+
143+
pv_status_t (*pv_koala_list_hardware_devices_func)(char ***, int32_t *) =
144+
load_symbol(dl_handle, "pv_koala_list_hardware_devices");
145+
if (!pv_koala_list_hardware_devices_func) {
146+
print_dl_error("failed to load `pv_koala_list_hardware_devices`");
147+
exit(EXIT_FAILURE);
148+
}
149+
150+
pv_status_t (*pv_koala_free_hardware_devices_func)(char **, int32_t) =
151+
load_symbol(dl_handle, "pv_koala_free_hardware_devices");
152+
if (!pv_koala_free_hardware_devices_func) {
153+
print_dl_error("failed to load `pv_koala_free_hardware_devices`");
154+
exit(EXIT_FAILURE);
155+
}
156+
157+
pv_status_t (*pv_get_error_stack_func)(char ***, int32_t *) =
158+
load_symbol(dl_handle, "pv_get_error_stack");
159+
if (!pv_get_error_stack_func) {
160+
print_dl_error("failed to load 'pv_get_error_stack_func'");
161+
exit(EXIT_FAILURE);
162+
}
163+
164+
void (*pv_free_error_stack_func)(char **) =
165+
load_symbol(dl_handle, "pv_free_error_stack");
166+
if (!pv_free_error_stack_func) {
167+
print_dl_error("failed to load 'pv_free_error_stack_func'");
168+
exit(EXIT_FAILURE);
169+
}
170+
171+
char **message_stack = NULL;
172+
int32_t message_stack_depth = 0;
173+
pv_status_t error_status = PV_STATUS_RUNTIME_ERROR;
174+
175+
char **hardware_devices = NULL;
176+
int32_t num_hardware_devices = 0;
177+
pv_status_t status = pv_koala_list_hardware_devices_func(&hardware_devices, &num_hardware_devices);
178+
if (status != PV_STATUS_SUCCESS) {
179+
fprintf(
180+
stderr,
181+
"Failed to list hardware devices with `%s`.\n",
182+
pv_status_to_string_func(status));
183+
error_status = pv_get_error_stack_func(&message_stack, &message_stack_depth);
184+
if (error_status != PV_STATUS_SUCCESS) {
185+
fprintf(
186+
stderr,
187+
".\nUnable to get Koala error state with '%s'.\n",
188+
pv_status_to_string_func(error_status));
189+
exit(EXIT_FAILURE);
190+
}
191+
192+
if (message_stack_depth > 0) {
193+
fprintf(stderr, ":\n");
194+
print_error_message(message_stack, message_stack_depth);
195+
pv_free_error_stack_func(message_stack);
196+
}
197+
exit(EXIT_FAILURE);
198+
}
199+
200+
for (int32_t i = 0; i < num_hardware_devices; i++) {
201+
fprintf(stdout, "%s\n", hardware_devices[i]);
202+
}
203+
pv_koala_free_hardware_devices_func(hardware_devices, num_hardware_devices);
204+
close_dl(dl_handle);
205+
}
125206

126207
int picovoice_main(int argc, char *argv[]) {
127208
const char *library_path = NULL;
128209
const char *model_path = NULL;
129210
const char *access_key = NULL;
130211
const char *input_path = NULL;
131212
const char *output_path = NULL;
213+
const char *device = NULL;
214+
bool show_inference_devices = false;
132215

133216
int c;
134-
while ((c = getopt_long(argc, argv, "l:m:a:i:o:", long_options, NULL)) != -1) {
217+
while ((c = getopt_long(argc, argv, "zl:m:a:y:i:o:", long_options, NULL)) != -1) {
135218
switch (c) {
136219
case 'l':
137220
library_path = optarg;
@@ -148,16 +231,37 @@ int picovoice_main(int argc, char *argv[]) {
148231
case 'o':
149232
output_path = optarg;
150233
break;
234+
case 'y':
235+
device = optarg;
236+
break;
237+
case 'z':
238+
show_inference_devices = true;
239+
break;
151240
default:
152241
exit(EXIT_FAILURE);
153242
}
154243
}
155244

245+
if (show_inference_devices) {
246+
if (!library_path) {
247+
fprintf(stderr, "`library_path` is required to view available inference devices.\n");
248+
print_usage(argv[0]);
249+
exit(EXIT_FAILURE);
250+
}
251+
252+
print_inference_devices(library_path);
253+
return EXIT_SUCCESS;
254+
}
255+
156256
if (!library_path || !access_key || !input_path || !output_path) {
157257
print_usage(argv[0]);
158258
exit(EXIT_FAILURE);
159259
}
160260

261+
if (device == NULL) {
262+
device = "best";
263+
}
264+
161265
void *koala_library = open_dl(library_path);
162266
if (!koala_library) {
163267
fprintf(stderr, "Failed to open library at '%s'.\n", library_path);
@@ -177,7 +281,7 @@ int picovoice_main(int argc, char *argv[]) {
177281
exit(EXIT_FAILURE);
178282
}
179283

180-
pv_status_t (*pv_koala_init_func)(const char *, const char *, pv_koala_t **) =
284+
pv_status_t (*pv_koala_init_func)(const char *, const char *, const char *, pv_koala_t **) =
181285
load_symbol(koala_library, "pv_koala_init");
182286
if (!pv_koala_init_func) {
183287
print_dl_error("Failed to load 'pv_koala_init'");
@@ -229,7 +333,7 @@ int picovoice_main(int argc, char *argv[]) {
229333
}
230334

231335
pv_koala_t *koala = NULL;
232-
pv_status_t koala_status = pv_koala_init_func(access_key, model_path, &koala);
336+
pv_status_t koala_status = pv_koala_init_func(access_key, model_path, device, &koala);
233337
if (koala_status != PV_STATUS_SUCCESS) {
234338
fprintf(stderr, "Failed to init with '%s'", pv_status_to_string_func(koala_status));
235339
char **message_stack = NULL;

0 commit comments

Comments
 (0)