Skip to content

Commit

Permalink
FEAT: added possibility to specify an engine time when sound should b…
Browse files Browse the repository at this point in the history
…e started (requires at least Rebol 3.13.1)
  • Loading branch information
Oldes committed Sep 10, 2023
1 parent 09df897 commit 28fb462
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 37 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,12 @@ Pause sound playback
Start sound or device playback
* `handle` `[handle!]` ma-sound or ma-engine handle
* `/loop` Turn looping on (only for sounds)
* `/seek` Specify starting position
* `frames` `[integer! time!]`
* `/fade`
* `in` `[integer! time!]` PCM frames or time (only for sounds)
* `/seek` Starting position
* `frames` `[integer! time!]` PCM frames or time
* `/fade` Fade in the sound
* `in` `[integer! time!]` PCM frames or time
* `/at` Absolute engine time when the sound should be started
* `time` `[integer! time!]` PCM frames or time

#### `stop` `:handle`
Stop sound or device playback
Expand Down
42 changes: 33 additions & 9 deletions src/miniaudio-commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ u32 word_playback;
u32 word_capture;




static ma_uint64 abs_sound_frames(RXIARG *arg, ma_sound *sound) {
ma_engine *engine = ma_sound_get_engine(sound);
return arg->uint64 + ma_engine_get_time_in_pcm_frames(engine);
Expand All @@ -81,6 +83,7 @@ static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput,
standard processing.
*/
ma_engine_read_pcm_frames((ma_engine*)pDevice->pUserData, pOutput, frameCount, NULL);

}


Expand All @@ -102,8 +105,8 @@ int MAEngine_free(void* hndl) {
if (!hndl) return 0;
hob = (REBHOB *)hndl;

printf("release engine: %p\n", hob->data);

printf("release engine: %p is referenced: %i\n", hob->data, IS_MARK_HOB(hob) != 0);
UNMARK_HOB(hob);
blk = hob->series;
if (blk) {
int i = blk->tail;
Expand Down Expand Up @@ -183,9 +186,18 @@ int MASound_free(void* hndl) {
REBHOB *hob;
if (!hndl) return 0;
hob = (REBHOB *)hndl;
printf("release sound: %p\n", hob->data);
printf("release sound: %p is referenced: %i\n", hob->data, IS_MARK_HOB(hob) != 0);

ma_sound *sound = (ma_sound*)hob->data;

// Don't release it, if not referenced but still playing...
if(!IS_MARK_HOB(hob) && ma_sound_is_playing(sound)) {
puts("preventing sound release?");
//MARK_HOB(hob);
//return 0;
}

UNMARK_HOB(hob);
ma_sound_uninit(sound);
if (hob->series) {
RESET_SERIES(hob->series);
Expand Down Expand Up @@ -637,29 +649,41 @@ COMMAND cmd_start(RXIFRM *frm, void *ctx) {
ma_sound *sound;
my_engine *engine;
ma_uint64 sampleRate;
REBI64 frame = 0;
ma_uint64 frame = 0;
REBHOB *hob = RXA_HANDLE_CONTEXT(frm, 1);
if (!IS_USED_HOB(hob)) return RXR_FALSE; // already released handle!

if (RXA_HANDLE_TYPE(frm, 1) == Handle_MASound) {
sound = ARG_MASound(1);
if (sound == NULL) return RXR_FALSE;

ma_sound_set_looping(sound, RXA_REF(frm, 2));

if (RXA_REF(frm, 3)) {
if (RXA_INT64(frm, 4) < 0) RXA_INT64(frm, 4) = 0;
if (RXA_TYPE(frm, 4) == RXT_INTEGER) {
frame = RXA_INT64(frm, 4);
frame = RXA_UINT64(frm, 4);
} else {
sampleRate = ma_engine_get_sample_rate(ma_sound_get_engine(sound));
frame = (RXA_TIME(frm, 4) * sampleRate) / 1000000000; // rate is per second
}
if (frame < 0) frame = 0;
}

ma_sound_set_looping(sound, RXA_REF(frm, 2));
ma_sound_seek_to_pcm_frame(sound, frame);

if (RXA_REF(frm, 7)) { // /at
if (RXA_INT64(frm, 8) < 0) RXA_INT64(frm, 8) = 0;
if (RXA_TYPE(frm, 8) == RXT_INTEGER) {
frame = RXA_UINT64(frm, 8);
} else {
sampleRate = ma_engine_get_sample_rate(ma_sound_get_engine(sound));
frame = (RXA_TIME(frm, 8) * sampleRate) / 1000000000; // rate is per second
}
ma_sound_set_start_time_in_pcm_frames(sound, frame);
}

ma_sound_start(sound);

if (RXA_REF(frm, 5)) {
if (RXA_REF(frm, 5)) { // /fade
ma_uint64 fade;
switch(RXA_TYPE(frm, 6)) {
case RXT_INTEGER:
Expand Down
2 changes: 1 addition & 1 deletion src/miniaudio-rebol-extension.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ u32* arg_words;

static const char* init_block = MINIAUDIO_EXT_INIT_CODE;

int Common_mold(void* hndl, REBSER *ser);
int Common_mold(REBHOB *hob, REBSER *ser);

int MAEngine_free(void* hndl);
int MAEngine_get_path(REBHOB *hob, REBCNT word, REBCNT *type, RXIARG *arg);
Expand Down
6 changes: 3 additions & 3 deletions src/miniaudio-rebol-extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#define SERIES_TEXT(s) ((char*)SERIES_DATA(s))

#define MIN_REBOL_VER 3
#define MIN_REBOL_REV 12
#define MIN_REBOL_REV 13
#define MIN_REBOL_UPD 1
#define VERSION(a, b, c) (a << 16) + (b << 8) + c
#define MIN_REBOL_VERSION VERSION(MIN_REBOL_VER, MIN_REBOL_REV, MIN_REBOL_UPD)
Expand Down Expand Up @@ -103,14 +103,14 @@ enum ma_arg_words {W_ARG_0,
typedef int (*MyCommandPointer)(RXIFRM *frm, void *ctx);

#define MINIAUDIO_EXT_INIT_CODE \
"REBOL [Title: {Rebol MiniAudio Extension} Type: module Version: 1.0.0]\n"\
"REBOL [Title: {Rebol MiniAudio Extension} Type: module Version: 0.11.18.1]\n"\
"init-words: command [sound [block!] noise [block!]]\n"\
"get-devices: command [\"Retrive playback/capture device names\"]\n"\
"init-playback: command [\"Initialize a playback device\" index [integer!] /pause \"Don't start it automatically\"]\n"\
"load: command [\"Loads a file and returns sound's handle\" sound [file!]]\n"\
"play: command [{Loads a file (if not already loaded) and starts playing it. Returns a sound handle.} sound [file! handle!] \"Source file or a ma-sound handle\" /stream \"Do not load the entire sound into memory\" /loop \"Turn looping on\" /volume vol [percent! decimal!] /fade in [integer! time!] \"PCM frames or time\"]\n"\
"pause: command [\"Pause sound playback\" sound [handle!]]\n"\
"start: command [\"Start sound or device playback\" handle [handle!] \"ma-sound or ma-engine handle\" /loop \"Turn looping on (only for sounds)\" /seek \"Specify starting position\" frames [integer! time!] /fade in [integer! time!] \"PCM frames or time (only for sounds)\"]\n"\
"start: command [\"Start sound or device playback\" handle [handle!] \"ma-sound or ma-engine handle\" /loop \"Turn looping on (only for sounds)\" /seek \"Starting position\" frames [integer! time!] \"PCM frames or time\" /fade \"Fade in the sound\" in [integer! time!] \"PCM frames or time\" /at {Absolute engine time when the sound should be started} time [integer! time!] \"PCM frames or time\"]\n"\
"stop: command [\"Stop sound or device playback\" handle [handle!] \"ma-sound or ma-engine handle\" /fade out [integer! time!] \"PCM frames or time (only for sounds)\"]\n"\
"fade: command [\"Fade sound volume\" sound [handle!] frames [integer! time!] start [percent! decimal!] end [percent! decimal!]]\n"\
"seek: command [\"Seek to specified position\" sound [handle!] frames [integer! time!] /relative \"Relative to the current sound position\"]\n"\
Expand Down
18 changes: 11 additions & 7 deletions src/miniaudio-rebol-extension.r3
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ REBOL [
type: module
date: 8-Sep-2023
home: https://github.com/Oldes/Rebol-MiniAudio
version: 0.11.18.0
version: 0.11.18.1
author: @Oldes
]

Expand Down Expand Up @@ -36,10 +36,14 @@ commands: [

start: [
"Start sound or device playback"
handle [handle!] "ma-sound or ma-engine handle"
/loop "Turn looping on (only for sounds)"
/seek "Specify starting position" frames [integer! time!]
/fade in [integer! time!] "PCM frames or time (only for sounds)"
handle [handle!] "ma-sound or ma-engine handle"
/loop "Turn looping on (only for sounds)"
/seek "Starting position"
frames [integer! time!] "PCM frames or time"
/fade "Fade in the sound"
in [integer! time!] "PCM frames or time"
/at "Absolute engine time when the sound should be started"
time [integer! time!] "PCM frames or time"
]
stop: [
"Stop sound or device playback"
Expand Down Expand Up @@ -134,7 +138,7 @@ arg-words: [
]

;-------------------------------------- ----------------------------------------
reb-code: {REBOL [Title: {Rebol MiniAudio Extension} Type: module Version: 0.11.18.0]}
reb-code: {REBOL [Title: {Rebol MiniAudio Extension} Type: module Version: 0.11.18.1]}
enu-commands: "" ;; command name enumerations
cmd-declares: "" ;; command function declarations
cmd-dispatch: "" ;; command functionm dispatcher
Expand Down Expand Up @@ -202,7 +206,7 @@ header: {
#define SERIES_TEXT(s) ((char*)SERIES_DATA(s))
#define MIN_REBOL_VER 3
#define MIN_REBOL_REV 12
#define MIN_REBOL_REV 13
#define MIN_REBOL_UPD 1
#define VERSION(a, b, c) (a << 16) + (b << 8) + c
#define MIN_REBOL_VERSION VERSION(MIN_REBOL_VER, MIN_REBOL_REV, MIN_REBOL_UPD)
Expand Down
30 changes: 17 additions & 13 deletions src/rebol-extension.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////
// File: rebol-extension.h
// Home: https://github.com/Oldes/Rebol3/
// Date: 6-Sep-2023/9:41:53
// Date: 10-Sep-2023/20:37:33
// Note: This file is amalgamated from these sources:
//
// reb-c.h
Expand Down Expand Up @@ -650,8 +650,8 @@ enum encoding_opts {
************************************************************************
**
** Title: Extension Types (Isolators)
** Build: 3.12.2
** Date: 6-Sep-2023
** Build: 3.13.1
** Date: 10-Sep-2023
** File: ext-types.h
**
** AUTO-GENERATED FILE - Do not modify. (From: make-boot.reb)
Expand Down Expand Up @@ -2119,7 +2119,7 @@ typedef void (*REBDOF)(REBVAL *ds); // DO evaltype dispatch function
typedef int (*REBPAF)(REBVAL *ds, REBVAL *p, REBCNT a); // Port action func

typedef int (*REB_HANDLE_FREE_FUNC)(void *hnd);
typedef int (*REB_HANDLE_MOLD_FUNC)(void *hnd, REBSER *ser);
typedef int (*REB_HANDLE_MOLD_FUNC)(REBHOB *hob, REBSER *ser);
typedef int (*REB_HANDLE_EVAL_PATH)(REBHOB *hob, REBCNT word, REBCNT *type, RXIARG *arg);

typedef void (*ANYFUNC)(void *);
Expand Down Expand Up @@ -2457,6 +2457,9 @@ typedef struct Reb_All {
# endif
#endif

// RXIARG has 16bytes and so there is room only for 15 args, because
// the first RXIARG in the RXIFRM contains types of all used command args.
#define MAX_RXI_ARGS 15

/* Prefix naming conventions:
Expand All @@ -2479,10 +2482,10 @@ typedef struct Reb_All {
typedef union rxi_arg_val {
void *addr;
i64 int64;
u64 uint64;
u64 uint64;
double dec64;
REBXYF pair;
REBYTE bytes[8];
REBYTE bytes[MAX_RXI_ARGS+1];
struct {
i32 int32a;
i32 int32b;
Expand Down Expand Up @@ -2528,7 +2531,7 @@ typedef union rxi_arg_val {

// Command function call frame:
typedef struct rxi_cmd_frame {
RXIARG args[8]; // arg values (128 bits each)
RXIARG args[MAX_RXI_ARGS+1]; // arg values (128 bits each)
} RXIFRM;

typedef struct rxi_cmd_context {
Expand All @@ -2549,6 +2552,7 @@ typedef int (*RXICAL)(int cmd, RXIFRM *args, REBCEC *ctx);

#define RXA_INT64(f,n) (RXA_ARG(f,n).int64)
#define RXA_INT32(f,n) (i32)(RXA_ARG(f,n).int64)
#define RXA_UINT64(f,n) (RXA_ARG(f,n).uint64)
#define RXA_DEC64(f,n) (RXA_ARG(f,n).dec64)
#define RXA_LOGIC(f,n) (RXA_ARG(f,n).int32a)
#define RXA_CHAR(f,n) (RXA_ARG(f,n).int32a)
Expand Down Expand Up @@ -3108,8 +3112,8 @@ enum {
************************************************************************
**
** Title: Event Types
** Build: 3.12.2
** Date: 6-Sep-2023
** Build: 3.13.1
** Date: 10-Sep-2023
** File: reb-evtypes.h
**
** AUTO-GENERATED FILE - Do not modify. (From: make-boot.reb)
Expand Down Expand Up @@ -3217,8 +3221,8 @@ enum event_keys {
************************************************************************
**
** Title: REBOL Host and Extension API
** Build: 3.12.2
** Date: 6-Sep-2023
** Build: 3.13.1
** Date: 10-Sep-2023
** File: reb-lib.reb
**
** AUTO-GENERATED FILE - Do not modify. (From: make-reb-lib.reb)
Expand All @@ -3229,8 +3233,8 @@ enum event_keys {
// These constants are created by the release system and can be used to check
// for compatiblity with the reb-lib DLL (using RL_Version.)
#define RL_VER 3
#define RL_REV 12
#define RL_UPD 2
#define RL_REV 13
#define RL_UPD 1

// Compatiblity with the lib requires that structs are aligned using the same
// method. This is concrete, not abstract. The macro below uses struct
Expand Down

0 comments on commit 28fb462

Please sign in to comment.