Skip to content

Commit 73f87cf

Browse files
committed
Added versions of from_samples and get_samples for 8, 16, and 32 bit PCM data
1 parent 3179606 commit 73f87cf

File tree

3 files changed

+368
-95
lines changed

3 files changed

+368
-95
lines changed

examples/tests-audio/tests-audio.c

Lines changed: 151 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ void clearIODiv();
1414
#define SECONDS 3
1515

1616
enum Tests {
17-
AudioFromSampleAndGetAudioSample,
17+
FromFloatPCMAndGetFloatPCM,
18+
From8bitPCMAndGet8bitPCM,
19+
From16bitPCMAndGet16bitPCM,
20+
From32bitPCMAndGet32bitPCM,
1821
GetMetadata,
1922
PlayAudioFromSample,
2023
PanAudioSample,
@@ -36,11 +39,14 @@ enum Tests {
3639
PlayAudioNodeRangeLoop,
3740
PlayAudioNodeRangeSampleRate,
3841
};
39-
const long START_TEST = AudioFromSampleAndGetAudioSample;
42+
const long START_TEST = FromFloatPCMAndGetFloatPCM;
4043
const long END_TEST = PlayAudioNodeRangeSampleRate;
4144

4245
const char* TEST_NAMES[30] = {
43-
"AudioFromSampleAndGetAudioSample",
46+
"FromFloatPCMAndGetFloatPCM",
47+
"From8bitPCMAndGet8bitPCM",
48+
"From16bitPCMAndGet16bitPCM",
49+
"From32bitPCMAndGet32bitPCM",
4450
"GetMetadata",
4551
"PlayAudioFromSample",
4652
"PanAudioSample",
@@ -252,57 +258,156 @@ void wait_for_playback_finish_event(int event_id, int playback_id) {
252258
#define ERR_MSG_LEN 30
253259
char err_msg[ERR_MSG_LEN];
254260

261+
void test_from_pcm_and_get_pcm(
262+
long test,
263+
long channels,
264+
long duration,
265+
long sample_rate,
266+
void* data,
267+
long (*generate_audio)(long, long, void*, long),
268+
void* (*get_audio)(long, long*, long*),
269+
bool (*validate)(void* data1, void* data2, long len)
270+
) {
271+
long node_id = generate_audio(channels, sample_rate, data, sample_rate*duration);
272+
273+
long total_len = duration*sample_rate*channels;
274+
275+
long num_channels = -1;
276+
277+
long single_channel_len = -1;
278+
279+
void* test_noise = twr_audio_get_float_pcm(node_id, &single_channel_len, &num_channels);
280+
281+
282+
if (num_channels != CHANNELS) {
283+
snprintf(err_msg, ERR_MSG_LEN-1, "expected %d channels, got %ld", CHANNELS, num_channels);
284+
test_fail(TEST_NAMES[test], err_msg);
285+
} else if (single_channel_len*num_channels != total_len) {
286+
snprintf(err_msg, ERR_MSG_LEN-1, "expected a length of %ld, got %ld", total_len, single_channel_len*num_channels);
287+
test_fail(TEST_NAMES[test], err_msg);
288+
} else if (validate(data, test_noise, total_len)) {
289+
test_success(TEST_NAMES[test]);
290+
} else {
291+
test_fail(TEST_NAMES[test], "Given audio didn't match what was retrieved!");
292+
}
293+
294+
twr_audio_free_id(node_id);
295+
296+
free(test_noise);
297+
}
298+
299+
bool validate_float(void* data1, void* data2, long len) {
300+
for (long i = 0; i < len; i++) {
301+
if (((float*)data1)[i] != ((float*)data2)[i]) {
302+
return false;
303+
}
304+
}
305+
return true;
306+
}
307+
bool validate_char(void* data1, void* data2, long len) {
308+
for (long i = 0; i < len; i++) {
309+
if (((char*)data1)[i] != ((char*)data2)[i]) {
310+
return false;
311+
}
312+
}
313+
return true;
314+
}
315+
bool validate_short(void* data1, void* data2, long len) {
316+
for (long i = 0; i < len; i++) {
317+
if (((short*)data1)[i] != ((short*)data2)[i]) {
318+
return false;
319+
}
320+
}
321+
return true;
322+
}
323+
bool validate_int(void* data1, void* data2, long len) {
324+
for (long i = 0; i < len; i++) {
325+
if (((int*)data1)[i] != ((int*)data2)[i]) {
326+
return false;
327+
}
328+
}
329+
return true;
330+
}
255331
void internal_test_case(int test, void* extra, bool full, enum CallType typ) {
256332
//set TEST_IS_RUNNING to false. A callback like wait_for_audio_load, test_next, or test_next_part
257333
// will set it back to true if needed. Otherwise, the test will have finished
258334
TEST_IS_RUNNING = false;
259335

260336
switch (test) {
261-
case AudioFromSampleAndGetAudioSample:
337+
case FromFloatPCMAndGetFloatPCM:
338+
{
339+
float* noise = generate_random_noise(CHANNELS * SAMPLE_RATE * SECONDS);
340+
test_from_pcm_and_get_pcm(test, CHANNELS, SECONDS, SAMPLE_RATE, (void*)noise,
341+
(long (*)(long, long, void*, long))twr_audio_from_float_pcm,
342+
(void* (*)(long, long*, long*))twr_audio_get_float_pcm,
343+
validate_float
344+
);
345+
free(noise);
346+
test_next(test, full, 0);
347+
}
348+
break;
349+
case From8bitPCMAndGet8bitPCM:
262350
{
263-
const long total_len = CHANNELS * SAMPLE_RATE * SECONDS;
351+
long total_len = CHANNELS * SAMPLE_RATE * SECONDS;
264352
float* noise = generate_random_noise(total_len);
265-
266-
long node_id = twr_audio_from_samples(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
267-
268-
long num_channels = -1;
269-
270-
long single_channel_len = -1;
271-
float* test_noise = twr_audio_get_samples(node_id, &single_channel_len, &num_channels);
272-
273-
274-
if (num_channels != CHANNELS) {
275-
snprintf(err_msg, ERR_MSG_LEN-1, "expected %d channels, got %ld", CHANNELS, num_channels);
276-
test_fail(TEST_NAMES[test], err_msg);
277-
} else if (single_channel_len*num_channels != total_len) {
278-
snprintf(err_msg, ERR_MSG_LEN-1, "expected a length of %ld, got %ld", total_len, single_channel_len*num_channels);
279-
test_fail(TEST_NAMES[test], err_msg);
280-
} else {
281-
bool valid = true;
282-
for (int i = 0; i < total_len; i++) {
283-
if (noise[i] != test_noise[i]) {
284-
valid = false;
285-
test_fail(TEST_NAMES[test], "audio generated for twr_audio_from_samples didn't match data returned from twr_audio_get_samples");
286-
break;
287-
}
288-
}
289-
if (valid) {
290-
test_success(TEST_NAMES[test]);
291-
}
353+
char* noise_char = (char*)malloc(sizeof(char) * total_len);
354+
for (long i = 0; i < total_len; i++) {
355+
noise_char[i] = (char)floor((noise[i] > 0 ? noise[i]/127 : noise[i]/128) + 0.5); //0.5 is added to make it round
292356
}
357+
free(noise);
293358

294-
twr_audio_free_id(node_id);
359+
test_from_pcm_and_get_pcm(test, CHANNELS, SECONDS, SAMPLE_RATE, (void*)noise_char,
360+
(long (*)(long, long, void*, long))twr_audio_from_8bit_pcm,
361+
(void* (*)(long, long*, long*))twr_audio_get_8bit_pcm,
362+
validate_char
363+
);
364+
free(noise_char);
365+
test_next(test, full, 0);
366+
}
367+
break;
368+
case From16bitPCMAndGet16bitPCM:
369+
{
370+
long total_len = CHANNELS * SAMPLE_RATE * SECONDS;
371+
float* noise = generate_random_noise(total_len);
372+
short* noise_char = (short*)malloc(sizeof(short) * total_len);
373+
for (long i = 0; i < total_len; i++) {
374+
noise_char[i] = (short)floor((noise[i] > 0 ? noise[i]/32767 : noise[i]/32768) + 0.5); //0.5 is added to make it round
375+
}
376+
free(noise);
295377

378+
test_from_pcm_and_get_pcm(test, CHANNELS, SECONDS, SAMPLE_RATE, (void*)noise_char,
379+
(long (*)(long, long, void*, long))twr_audio_from_16bit_pcm,
380+
(void* (*)(long, long*, long*))twr_audio_get_16bit_pcm,
381+
validate_short
382+
);
383+
free(noise_char);
384+
test_next(test, full, 0);
385+
}
386+
break;
387+
case From32bitPCMAndGet32bitPCM:
388+
{
389+
long total_len = CHANNELS * SAMPLE_RATE * SECONDS;
390+
float* noise = generate_random_noise(total_len);
391+
int* noise_char = (int*)malloc(sizeof(int) * total_len);
392+
for (long i = 0; i < total_len; i++) {
393+
noise_char[i] = (int)floor((noise[i] > 0 ? noise[i]/2147483648 : noise[i]/2147483648) + 0.5); //0.5 is added to make it round
394+
}
296395
free(noise);
297-
free(test_noise);
396+
397+
test_from_pcm_and_get_pcm(test, CHANNELS, SECONDS, SAMPLE_RATE, (void*)noise_char,
398+
(long (*)(long, long, void*, long))twr_audio_from_32bit_pcm,
399+
(void* (*)(long, long*, long*))twr_audio_get_32bit_pcm,
400+
validate_int
401+
);
402+
free(noise_char);
298403
test_next(test, full, 0);
299404
}
300405
break;
301406

302407
case GetMetadata:
303408
{
304409
float* noise = generate_random_noise(CHANNELS * SAMPLE_RATE * SECONDS);
305-
long node_id = twr_audio_from_samples(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE * SECONDS);
410+
long node_id = twr_audio_from_float_pcm(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE * SECONDS);
306411
free(noise);
307412

308413
struct AudioMetadata meta;
@@ -339,7 +444,7 @@ void internal_test_case(int test, void* extra, bool full, enum CallType typ) {
339444
case PlayAudioFromSample:
340445
{
341446
float* noise = generate_random_noise(CHANNELS * SAMPLE_RATE * SECONDS);
342-
long node_id = twr_audio_from_samples(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
447+
long node_id = twr_audio_from_float_pcm(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
343448

344449
twr_audio_play_volume(node_id, 0.5, 0.0);
345450
printf("Running test %s\n", TEST_NAMES[test]);
@@ -353,7 +458,7 @@ void internal_test_case(int test, void* extra, bool full, enum CallType typ) {
353458
case PanAudioSample:
354459
{
355460
float* noise = generate_random_noise(CHANNELS * SAMPLE_RATE * SECONDS);
356-
long node_id = twr_audio_from_samples(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
461+
long node_id = twr_audio_from_float_pcm(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
357462

358463
twr_audio_play_volume(node_id, 0.5, -0.5);
359464
printf("Running test %s\n", TEST_NAMES[test]);
@@ -383,7 +488,7 @@ void internal_test_case(int test, void* extra, bool full, enum CallType typ) {
383488
{
384489
if (typ != PlaybackFinished) {
385490
float* noise = generate_random_noise(CHANNELS * SAMPLE_RATE * SECONDS);
386-
long node_id = twr_audio_from_samples(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
491+
long node_id = twr_audio_from_float_pcm(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
387492

388493
printf("Running test %s\n", TEST_NAMES[test]);
389494
wait_for_playback_finish(test, full, node_id, 0, SAMPLE_RATE*SECONDS, false, SAMPLE_RATE, 50, 0);
@@ -407,7 +512,7 @@ void internal_test_case(int test, void* extra, bool full, enum CallType typ) {
407512
{
408513
#ifdef ASYNC
409514
float* noise = generate_random_noise(CHANNELS * SAMPLE_RATE * SECONDS);
410-
long node_id = twr_audio_from_samples(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
515+
long node_id = twr_audio_from_float_pcm(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
411516

412517
printf("Running test %s\n", TEST_NAMES[test]);
413518

@@ -457,7 +562,7 @@ void internal_test_case(int test, void* extra, bool full, enum CallType typ) {
457562
{
458563
if (extra == NULL) {
459564
float* noise = generate_random_noise(CHANNELS * SAMPLE_RATE * SECONDS);
460-
long node_id = twr_audio_from_samples(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
565+
long node_id = twr_audio_from_float_pcm(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
461566

462567
printf("Running test %s\n", TEST_NAMES[test]);
463568

@@ -522,7 +627,7 @@ void internal_test_case(int test, void* extra, bool full, enum CallType typ) {
522627
{
523628
if (extra == NULL) {
524629
float* noise = generate_random_noise(CHANNELS * SAMPLE_RATE * SECONDS);
525-
long node_id = twr_audio_from_samples(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
630+
long node_id = twr_audio_from_float_pcm(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
526631

527632
printf("Running test %s\n", TEST_NAMES[test]);
528633

@@ -640,7 +745,7 @@ void internal_test_case(int test, void* extra, bool full, enum CallType typ) {
640745
if (typ != NextTestPart) {
641746
state = malloc(sizeof(long) * 3);
642747
float* noise = generate_random_noise(CHANNELS * SAMPLE_RATE * SECONDS);
643-
long node_id = twr_audio_from_samples(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
748+
long node_id = twr_audio_from_float_pcm(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
644749

645750
long playback_id = twr_audio_play_volume(node_id, 0.5, 0.0);
646751
twr_audio_free_id(node_id);
@@ -676,7 +781,7 @@ void internal_test_case(int test, void* extra, bool full, enum CallType typ) {
676781
long prev_playback_id = (long)extra;
677782
if (typ != NextTestPart) {
678783
float* noise = generate_random_noise(CHANNELS * SAMPLE_RATE * SECONDS);
679-
long node_id = twr_audio_from_samples(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
784+
long node_id = twr_audio_from_float_pcm(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE*SECONDS);
680785
free(noise);
681786
long playback_id = twr_audio_play(node_id);
682787
twr_audio_free_id(node_id);
@@ -766,7 +871,7 @@ void internal_test_case(int test, void* extra, bool full, enum CallType typ) {
766871
long target_runtime = 1;
767872
if (typ != NextTestPart) {
768873
float* noise = generate_random_noise(SAMPLE_RATE * SECONDS * CHANNELS);
769-
long node_id = twr_audio_from_samples(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE * SECONDS);
874+
long node_id = twr_audio_from_float_pcm(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE * SECONDS);
770875
free(noise);
771876

772877
long playback_id = twr_audio_play_range(node_id, 0, SAMPLE_RATE * target_runtime);
@@ -796,7 +901,7 @@ void internal_test_case(int test, void* extra, bool full, enum CallType typ) {
796901
double target_runtime = 0.15;
797902
if (typ != NextTestPart) {
798903
float* noise = generate_random_noise(SAMPLE_RATE * SECONDS * CHANNELS);
799-
long node_id = twr_audio_from_samples(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE * SECONDS);
904+
long node_id = twr_audio_from_float_pcm(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE * SECONDS);
800905
free(noise);
801906

802907
struct PlayRangeFields fields = twr_audio_default_play_range();
@@ -829,7 +934,7 @@ void internal_test_case(int test, void* extra, bool full, enum CallType typ) {
829934
long n_sample_rate = SAMPLE_RATE * 2;
830935
if (typ != NextTestPart) {
831936
float* noise = generate_random_noise(SAMPLE_RATE * SECONDS * CHANNELS);
832-
long node_id = twr_audio_from_samples(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE * SECONDS);
937+
long node_id = twr_audio_from_float_pcm(CHANNELS, SAMPLE_RATE, noise, SAMPLE_RATE * SECONDS);
833938
free(noise);
834939

835940
struct PlayRangeFields fields = twr_audio_default_play_range();

source/twr-c/twr-audio.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,16 @@
55
extern "C" {
66
#endif
77

8-
__attribute__((import_name("twrAudioFromSamples"))) long twr_audio_from_samples(long num_channels, long sample_rate, float* data, long singleChannelDataLen);
8+
9+
__attribute__((import_name("twrAudioFromFloatPCM"))) long twr_audio_from_float_pcm(long num_channels, long sample_rate, float* data, long singleChannelDataLen);
10+
__attribute__((import_name("twrAudioFrom8bitPCM"))) long twr_audio_from_8bit_pcm(long number_channels, long sample_rate, char* data, long singleChannelDataLen);
11+
__attribute__((import_name("twrAudioFrom16bitPCM"))) long twr_audio_from_16bit_pcm(long number_channels, long sample_rate, short* data, long singleChannelDataLen);
12+
__attribute__((import_name("twrAudioFrom32bitPCM"))) long twr_audio_from_32bit_pcm(long number_channels, long sample_rate, int* data, long singleChannelDataLen);
13+
14+
__attribute__((import_name("twrAudioGetFloatPCM"))) float* twr_audio_get_float_pcm(long node_id, long* singleChannelDataLenPtr, long* numChannelsPtr);
15+
__attribute__((import_name("twrAudioGet8bitPCM"))) char* twr_audio_get_8bit_pcm(long node_id, long* singleChannelDataLenPtr, long* numChannelsPtr);
16+
__attribute__((import_name("twrAudioGet16bitPCM"))) short* twr_audio_get_16bit_pcm(long node_id, long* singleChannelDataLenPtr, long* numChannelsPtr);
17+
__attribute__((import_name("twrAudioGet32bitPCM"))) int* twr_audio_get_32bit_pcm(long node_id, long* singleChannelDataLenPtr, long* numChannelsPtr);
918

1019
__attribute__((import_name("twrAudioPlay"))) long twr_audio_play(long node_id);
1120
__attribute__((import_name("twrAudioPlay"))) long twr_audio_play_volume(long node_id, double volume, double pan);
@@ -36,7 +45,6 @@ long twr_audio_play_range_sync_ex(long node_id, long start_sample, long end_samp
3645
__attribute__((import_name("twrAudioLoadSync"))) long twr_audio_load_sync(char* url);
3746
__attribute__((import_name("twrAudioLoad"))) long twr_audio_load(int event_id, char* url);
3847
__attribute__((import_name("twrAudioQueryPlaybackPosition"))) long twr_audio_query_playback_position(long playback_id);
39-
__attribute__((import_name("twrAudioGetSamples"))) float* twr_audio_get_samples(long node_id, long* singleChannelDataLenPtr, long* channelPtr);
4048
__attribute__((import_name("twrAudioFreeID"))) void twr_audio_free_id(long node_id);
4149

4250
__attribute__((import_name("twrAudioStopPlayback"))) void twr_audio_stop_playback(long playback_id);

0 commit comments

Comments
 (0)