Skip to content

Commit

Permalink
Add vu peak callback.
Browse files Browse the repository at this point in the history
  • Loading branch information
devsaurus committed May 7, 2016
1 parent 2093247 commit 5b1aee5
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 4 deletions.
10 changes: 10 additions & 0 deletions app/modules/pcm.c
Expand Up @@ -36,6 +36,7 @@ static int pcm_drv_free( lua_State *L )
UNREF_CB( cfg->cb_drained_ref );
UNREF_CB( cfg->cb_paused_ref );
UNREF_CB( cfg->cb_stopped_ref );
UNREF_CB( cfg->cb_vu_ref );
UNREF_CB( cfg->self_ref );

if (cfg->bufs[0].data) {
Expand Down Expand Up @@ -160,6 +161,13 @@ static int pcm_drv_on( lua_State *L )
} else if ((len == 7) && (c_strcmp( event, "stopped" ) == 0)) {
luaL_unref( L, LUA_REGISTRYINDEX, cfg->cb_stopped_ref);
cfg->cb_stopped_ref = COND_REF( is_func );
} else if ((len == 2) && (c_strcmp( event, "vu" ) == 0)) {
luaL_unref( L, LUA_REGISTRYINDEX, cfg->cb_vu_ref);
cfg->cb_vu_ref = COND_REF( is_func );

int freq = luaL_optinteger( L, 4, 10 );
luaL_argcheck( L, (freq > 0) && (freq <= 200), 4, "invalid range" );
cfg->vu_freq = (uint8_t)freq;
} else {
if (is_func) {
// need to pop pushed function arg
Expand Down Expand Up @@ -187,13 +195,15 @@ static int pcm_new( lua_State *L )
cfg->self_ref = LUA_NOREF;
cfg->cb_data_ref = cfg->cb_drained_ref = LUA_NOREF;
cfg->cb_paused_ref = cfg->cb_stopped_ref = LUA_NOREF;
cfg->cb_vu_ref = LUA_NOREF;

cfg->bufs[0].buf_size = cfg->bufs[1].buf_size = 0;
cfg->bufs[0].data = cfg->bufs[1].data = NULL;
cfg->bufs[0].len = cfg->bufs[1].len = 0;
cfg->bufs[0].rpos = cfg->bufs[1].rpos = 0;
cfg->bufs[0].empty = cfg->bufs[1].empty = TRUE;

cfg->data_vu_task = task_get_id( pcm_data_vu_task );
cfg->data_play_task = task_get_id( pcm_data_play_task );
cfg->start_play_task = task_get_id( pcm_start_play_task );

Expand Down
20 changes: 20 additions & 0 deletions app/pcm/drv_sigma_delta.c
Expand Up @@ -22,8 +22,23 @@ static void ICACHE_RAM_ATTR drv_sd_timer_isr( os_param_t arg )
}

if (!buf->empty) {
uint16_t tmp;
// buffer is not empty, continue reading

tmp = abs((int16_t)(buf->data[buf->rpos]) - 128);
if (tmp > cfg->vu_peak_tmp) {
cfg->vu_peak_tmp = tmp;
}
cfg->vu_samples_tmp++;
if (cfg->vu_samples_tmp >= cfg->vu_req_samples) {
cfg->vu_peak = cfg->vu_peak_tmp;

task_post_low( cfg->data_vu_task, (os_param_t)cfg );

cfg->vu_samples_tmp = 0;
cfg->vu_peak_tmp = 0;
}

platform_sigma_delta_set_target( buf->data[buf->rpos++] );
if (buf->rpos >= buf->len) {
// buffer data consumed, request to re-fill it
Expand Down Expand Up @@ -64,6 +79,11 @@ static uint8_t drv_sd_close( cfg_t *cfg )

static uint8_t drv_sd_play( cfg_t *cfg )
{
// VU control: derive callback frequency
cfg->vu_req_samples = (uint16_t)((1000000L / (uint32_t)cfg->vu_freq) / (uint32_t)pcm_rate_def[cfg->rate]);
cfg->vu_samples_tmp = 0;
cfg->vu_peak_tmp = 0;

// (re)start hardware timer ISR to feed the sigma-delta
if (platform_hw_timer_init( drv_sd_hw_timer_owner, FRC1_SOURCE, TRUE )) {
platform_hw_timer_set_func( drv_sd_hw_timer_owner, drv_sd_timer_isr, (os_param_t)cfg );
Expand Down
9 changes: 7 additions & 2 deletions app/pcm/pcm.h
Expand Up @@ -64,12 +64,16 @@ typedef struct {
uint8_t rbuf_idx; // read by ISR
uint8_t fbuf_idx; // fill by data task
// task handles
task_handle_t data_play_task, start_play_task;
task_handle_t data_vu_task, data_play_task, start_play_task;
// callback fn refs
int self_ref;
int cb_data_ref, cb_drained_ref, cb_paused_ref, cb_stopped_ref;
int cb_data_ref, cb_drained_ref, cb_paused_ref, cb_stopped_ref, cb_vu_ref;
// data buffers
pcm_buf_t bufs[2];
// vu measuring
uint8_t vu_freq;
uint16_t vu_req_samples, vu_samples_tmp;
uint16_t vu_peak_tmp, vu_peak;
// sigma-delta: output pin
int pin;
} cfg_t;
Expand All @@ -91,6 +95,7 @@ typedef struct {
} pud_t;


void pcm_data_vu_task( task_param_t param, uint8 prio );
void pcm_data_play_task( task_param_t param, uint8 prio );

#endif /* _PCM_H */
13 changes: 13 additions & 0 deletions app/pcm/pcm_core.c
Expand Up @@ -27,6 +27,19 @@ static void dispatch_callback( lua_State *L, int self_ref, int cb_ref, int retur
}
}

void pcm_data_vu_task( task_param_t param, uint8 prio )
{
cfg_t *cfg = (cfg_t *)param;
lua_State *L = lua_getstate();

if (cfg->cb_vu_ref != LUA_NOREF) {
lua_rawgeti( L, LUA_REGISTRYINDEX, cfg->cb_vu_ref );
lua_rawgeti( L, LUA_REGISTRYINDEX, cfg->self_ref );
lua_pushnumber( L, (LUA_NUMBER)(cfg->vu_peak) );
lua_call( L, 2, 0 );
}
}

void pcm_data_play_task( task_param_t param, uint8 prio )
{
cfg_t *cfg = (cfg_t *)param;
Expand Down
5 changes: 3 additions & 2 deletions docs/en/modules/pcm.md
Expand Up @@ -61,15 +61,16 @@ none
Register callback functions for events.

#### Syntax
`drv:on(event[, cb_fn])`
`drv:on(event[, cb_fn[, freq]])`

#### Parameters
- `event` identifier, one of:
- `data` callback function is supposed to return a string containing the next chunk of data.
- `drained` playback was stopped due to lack of data. The last 2 invocations of the `data` callback didn't provide new chunks in time (intentionally or unintentionally) and the internal buffers were fully consumed.
- `paused` playback was paused by `pcm.drv:pause()`.
- `stopped` playback was stopped by `pcm.drv:stop()`.
- `cb_fn` callback function for the specified event. Unregisters previous function if omitted.
- `vu` new peak data, `cb_fn` is triggered `freq` times per second (1 to 200 Hz).
- `cb_fn` callback function for the specified event. Unregisters previous function if omitted. First parameter is `drv`, followed by peak data for `vu` callback.

#### Returns
`nil`
Expand Down
4 changes: 4 additions & 0 deletions lua_examples/pcm/play_network.lua
Expand Up @@ -139,6 +139,10 @@ function M.init(pin)
--_drv:on("stopped", cb_stopped)
end

function M.vu(cb, freq)
_drv:on("vu", cb, freq)
end

function M.close()
stop_stream()
_drv:close()
Expand Down

0 comments on commit 5b1aee5

Please sign in to comment.