All pastes #650314 Raw Edit

DSP plugin examples

public c v1 · immutable
#650314 ·published 2007-08-08 20:34 UTC
rendered paste body
/*************************************************************************** *             __________               __   ___. *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  / *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  < *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \ *                     \/            \/     \/    \/            \/ * $Id:$ * * Copyright (C) 2006 Michael Sevakis  * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/#include "plugin.h"/* Button mapping */#if CONFIG_KEYPAD == IRIVER_H100_PAD#define EFFECT_QUIT BUTTON_ON#elif CONFIG_KEYPAD == IAUDIO_X5_PAD#define EFFECT_QUIT BUTTON_POWER#endifPLUGIN_HEADERPLUGIN_IRAM_DECLAREstatic struct plugin_api* rb;static int queue_size;/* Imporant to leave enough room behind effect_index to allow for delays like screen updates */static volatile int wr_index = 4;static volatile int rd_index = 0;static int effect_index      = 4; /* one ahead to account for preincrement of wr_index */static unsigned long effect_thread_stack[DEFAULT_STACK_SIZE] IBSS_ATTR;static bool stop_effect = false;#define CHUNK_SAMPLES   128#define CHUNK_SIZE      (CHUNK_SAMPLES*4)#define NUM_CHUNKS      8 /* power of 2 */#define CHUNK_MASK      (NUM_CHUNKS-1)#define NEXT_CHUNK(x)   (((x) + 1) & CHUNK_MASK)typedef int32_t (* buffer_t)[CHUNK_SAMPLES];buffer_t __attribute__((aligned(16))) queue;/* Effect data */struct lfo {	int32_t phase, delta;};struct delay {	size_t writepos;	size_t mask;	int32_t delay;	int16_t *delayline;};struct lfo trilfo = { 0, 0xffffffff/44100/5};int16_t delayline_l[65536], delayline_r[65536];struct delay delay1 = { 0, 0xffff, (10000 << 15) + 0x1fff, delayline_l };static inline int32_t saw_lfo(struct lfo *l){    int32_t ret = l->phase;    l->phase += l->delta;    return ret;}static inline int32_t tri_lfo(struct lfo *l){    int32_t ret = (abs(l->phase + 0x3fffffff) - 0x3fffffff) << 1;    l->phase += l->delta;    return ret;}static inline int32_t par_lfo(struct lfo *l){    int32_t shift_phase = l->phase >> 16;    int32_t ret = 8*shift_phase*((1 << 15) - abs(shift_phase));    l->phase += l->delta;    return ret;}static void delay_process(int16_t *data, struct delay *d, int num) ICODE_ATTR;static void delay_process(int16_t *data, struct delay *d, int num){	int i;	size_t mask = d->mask;    size_t writepos = d->writepos;	for (i = 0; i < num; ++i) {		d->delay = (441 << 15) + par_lfo(&trilfo)/1600;		size_t r = writepos - (d->delay >> 15);		int32_t frac = 0x8000 - (d->delay & 0x7fff);		const int32_t xm1 = d->delayline[(r - 1) & mask];		const int32_t x0 = d->delayline[r & mask];		const int32_t xp1 = d->delayline[(r + 1) & mask];		const int32_t xp2 = d->delayline[(r + 2) & mask];        		const int32_t c = (xp1 - xm1)/2;        const int32_t v = x0 - xp1;        const int32_t w = c + v;        const int32_t a = w + v + (xp2 - x0)/2;        const int32_t b = w + a;            		int32_t output = (((((a*frac >> 15) - b)*frac >> 15) + c)*frac >> 15) + x0;		int32_t input = *data;		d->delayline[writepos] = input + output*2/10;		*data++ = (input + output)/2;		*data++ = (input + output)/2;		writepos = (writepos + 1) & mask;	}    d->writepos = writepos;}static void play_callback(unsigned char **start, size_t *size) ICODE_ATTR;static void play_callback(unsigned char **start, size_t *size){    rd_index = NEXT_CHUNK(rd_index);    *start = (unsigned char *)queue[rd_index];    *size  = CHUNK_SIZE;}static int record_callback(int status) ICODE_ATTR;static int record_callback(int status){    wr_index = NEXT_CHUNK(wr_index);    rb->pcm_record_more(queue[wr_index], CHUNK_SIZE);    return 0;    (void)status;}static void effect_thread(void) ICODE_ATTR;static void effect_thread(void){    int y = 0;    while (!stop_effect)    {        /* Wait for at least one chunk of data available */        while (wr_index == effect_index)        {            rb->yield();            if (stop_effect)                goto effect_done;        }        do        {            int16_t *ptr = (int16_t *)queue[effect_index];            delay_process(ptr, &delay1, CHUNK_SAMPLES);                        effect_index  = NEXT_CHUNK(effect_index);            if (++y >= 8)            {                rb->yield();                y = 0;            }        }        while (effect_index != wr_index);    }effect_done:    /* main thread waits for this to turn false again */    stop_effect = false;    rb->remove_thread(NULL);}/* this is the plugin entry point */enum plugin_status plugin_start(struct plugin_api* api, void* parameter){    PLUGIN_IRAM_INIT(api);    rb = api;    queue = (buffer_t)rb->plugin_get_audio_buffer(&queue_size);    rb->memset(queue, 0, CHUNK_SIZE*NUM_CHUNKS);    rb->memset(delayline_l, 0, sizeof(delayline_l));    rb->pcm_init_recording();    rb->pcm_set_frequency(SAMPR_44);    rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);    rb->rec_set_source(AUDIO_SRC_LINEIN, SRCF_RECORDING);    rb->pcm_apply_settings(true);    rb->cpu_boost(true);    rb->pcm_record_data(record_callback, queue[wr_index], CHUNK_SIZE);    rb->pcm_play_data(play_callback, NULL, 0);    rb->sound_set(SOUND_VOLUME, rb->sound_default(SOUND_VOLUME));    rb->audio_set_recording_gain(rb->sound_default(SOUND_LEFT_GAIN) + 10,            rb->sound_default(SOUND_RIGHT_GAIN) + 10, AUDIO_GAIN_LINEIN);    /* Start a thread for processing the audio */    rb->create_thread(effect_thread, effect_thread_stack,                      sizeof(effect_thread_stack), "effect thread",                      PRIORITY_RECORDING);    while (rb->button_get_w_tmo(HZ/10) != EFFECT_QUIT)    {        char buf[32];        rb->snprintf(buf, ARRAYLEN(buf), "rd: %d ef:%d wr: %d",                     rd_index, effect_index, wr_index);        rb->lcd_puts(0, 0, buf);        rb->yield();        rb->lcd_update();        rb->yield();    }    /* stop effect thread - it will remove itself */    stop_effect = true;    while (stop_effect)        rb->yield();    rb->pcm_play_stop();    rb->pcm_stop_recording();    rb->pcm_close_recording();    rb->cpu_boost(false);    rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);    rb->pcm_set_frequency(HW_SAMPR_DEFAULT);    rb->rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);    rb->pcm_apply_settings(true);    return PLUGIN_OK;    (void)parameter;}