1
0
Fork 0
forked from len0rd/rockbox

More work on PDBox by Wincent Balin. The PDBox plug-in is now working with the pdpod_test.pd file from the PureData.zip archive

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21816 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Peter D'Hoye 2009-07-12 18:44:26 +00:00
parent a3a8708cdf
commit 66a0492ab7
6 changed files with 208 additions and 155 deletions

View file

@ -313,7 +313,6 @@ void dsp_tick(void)
t_int *ip; t_int *ip;
for (ip = dsp_chain; *ip; ) ip = (*(t_perfroutine)(*ip))(ip); for (ip = dsp_chain; *ip; ) ip = (*(t_perfroutine)(*ip))(ip);
dsp_phase++; dsp_phase++;
printf("%d\n", dsp_phase);
} }
} }

View file

@ -507,7 +507,12 @@ t_symbol *dogensym(char *s, t_symbol *oldsym)
t_symbol *gensym(char *s) t_symbol *gensym(char *s)
{ {
printf("gensym: %s\n", s); // printf("gensym: %s\n", s);
#ifdef ROCKBOX
if(s == NULL)
return dogensym("/", 0);
else
#endif
return(dogensym(s, 0)); return(dogensym(s, 0));
} }

View file

@ -25,25 +25,32 @@
#include "m_pd.h" #include "m_pd.h"
#include "s_stuff.h" #include "s_stuff.h"
/* Sound output buffer. */ /* Extern variables. */
#define AUDIO_OUTPUT_BLOCKS 3 extern float sys_dacsr;
static struct pdbox_audio_block audio_output[AUDIO_OUTPUT_BLOCKS]; extern t_sample *sys_soundout;
static unsigned int output_head; extern t_sample *sys_soundin;
static unsigned int output_tail;
static unsigned int output_fill; /* Output buffer. */
#define OUTBUFSIZE 3
static struct audio_buffer outbuf[OUTBUFSIZE];
static unsigned int outbuf_head;
static unsigned int outbuf_tail;
static unsigned int outbuf_fill;
/* Playing status. */
static bool playing;
/* Open audio. */ /* Open audio. */
void rockbox_open_audio(int rate) void rockbox_open_audio(int rate)
{ {
unsigned int i; unsigned int i;
/* Initialize output buffer. */ /* No sound yet. */
for(i = 0; i < AUDIO_OUTPUT_BLOCKS; i++) playing = false;
audio_output[i].fill = 0;
output_head = 0; /* Stop playing to reconfigure audio settings. */
output_tail = 0; rb->pcm_play_stop();
output_fill = 0;
#if INPUT_SRC_CAPS != 0 #if INPUT_SRC_CAPS != 0
/* Select playback */ /* Select playback */
@ -53,6 +60,15 @@ void rockbox_open_audio(int rate)
/* Set sample rate of the audio buffer. */ /* Set sample rate of the audio buffer. */
rb->pcm_set_frequency(rate); rb->pcm_set_frequency(rate);
rb->pcm_apply_settings();
/* Initialize output buffer. */
for(i = 0; i < OUTBUFSIZE; i++)
outbuf[i].fill = 0;
outbuf_head = 0;
outbuf_tail = 0;
outbuf_fill = 0;
} }
/* Close audio. */ /* Close audio. */
@ -61,84 +77,115 @@ void rockbox_close_audio(void)
/* Stop playback. */ /* Stop playback. */
rb->pcm_play_stop(); rb->pcm_play_stop();
/* Reset playing status. */
playing = false;
/* Restore default sampling rate. */ /* Restore default sampling rate. */
rb->pcm_set_frequency(HW_SAMPR_DEFAULT); rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
rb->pcm_apply_settings();
} }
/* Rockbox audio callback. */ /* Rockbox audio callback. */
void pdbox_get_more(unsigned char** start, size_t* size) void pdbox_get_more(unsigned char** start, size_t* size)
{ {
if(output_fill > 0) if(outbuf_fill > 0)
{ {
/* Store output data address and size. */ /* Store output data address and size. */
*start = (unsigned char*) audio_output[output_tail].data; *start = (unsigned char*) outbuf[outbuf_tail].data;
*size = audio_output[output_tail].fill; *size = sizeof(outbuf[outbuf_tail].data);
/* Advance tail index. */ /* Free this part of output buffer. */
audio_output[output_tail].fill = 0; outbuf[outbuf_tail].fill = 0;
output_fill--;
if(output_tail == AUDIO_OUTPUT_BLOCKS-1) /* Advance to the next part of output buffer. */
output_tail = 0; if(outbuf_tail == OUTBUFSIZE-1)
outbuf_tail = 0;
else else
output_tail++; outbuf_tail++;
/* Decrease output buffer fill. */
outbuf_fill--;
} }
else else
{ {
/* Reset playing status. */
playing = false;
/* Nothing to play. */ /* Nothing to play. */
*start = NULL; *start = NULL;
*size = 0; *size = 0;
return;
} }
} }
/* Audio I/O. */ /* Audio I/O. */
int rockbox_send_dacs(void) int rockbox_send_dacs(void)
{ {
/* Copy sys_output buffer. */
t_sample* left = sys_soundout + DEFDACBLKSIZE*0;
t_sample* right = sys_soundout + DEFDACBLKSIZE*1;
unsigned int samples_out = 0;
int16_t* out;
int sample;
/* Cancel if whole buffer filled. */
if(outbuf_fill >= OUTBUFSIZE-1)
return SENDDACS_NO;
/* Start playback if needed and possible. */ /* Write the block of sound. */
if(output_fill > 1 && write_block:
audio_output[output_tail].fill == PD_AUDIO_BLOCK_SIZE) for(out = outbuf[outbuf_head].data +
outbuf[outbuf_head].fill * PD_OUT_CHANNELS;
outbuf[outbuf_head].fill < (AUDIOBUFSIZE / PD_OUT_CHANNELS) &&
samples_out < DEFDACBLKSIZE;
left++, right++, samples_out++, outbuf[outbuf_head].fill++)
{ {
/* Start playback. */ /* Copy samples from both channels. */
rb->pcm_play_data(pdbox_get_more, sample = SCALE16(*left);
(unsigned char*) audio_output[output_tail].data, if(sample > 32767)
PD_AUDIO_BLOCK_SIZE); sample = 32767;
else if(sample < -32767)
sample = -32767;
*out++ = sample;
sample = SCALE16(*right);
if(sample > 32767)
sample = 32767;
else if(sample < -32767)
sample = -32767;
*out++ = sample;
}
/* Advance tail index. */ /* If part of output buffer filled... */
audio_output[output_tail].fill = PD_AUDIO_BLOCK_SIZE; if(outbuf[outbuf_head].fill >= (AUDIOBUFSIZE / PD_OUT_CHANNELS))
output_fill--; {
if(output_tail == AUDIO_OUTPUT_BLOCKS-1) /* Advance one part of output buffer. */
output_tail = 0; if(outbuf_head == OUTBUFSIZE-1)
outbuf_head = 0;
else else
output_tail++; outbuf_head++;
/* Increase fill counter. */
outbuf_fill++;
} }
/* If needed, fill the next frame. */
if(samples_out < DEFDACBLKSIZE)
goto write_block;
/* Clear Pure Data output buffer. */
memset(sys_soundout,
0,
sizeof(t_sample) * DEFDACBLKSIZE * PD_OUT_CHANNELS);
/* If still not playing... */
#if 0 if(!playing && outbuf_fill > 0)
if (sys_getrealtime() > timebefore + 0.002)
{ {
/* post("slept"); */ /* Start playing. */
return (SENDDACS_SLEPT); rb->pcm_play_data(pdbox_get_more, NULL, 0);
}
else /* Set status flag. */
#endif playing = true;
return (SENDDACS_YES);
} }
/* Placeholder. */ return SENDDACS_YES;
void rockbox_listdevs(void)
{
} }
#if 0
/* Scanning for devices */
void rockbox_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize)
{
}
#endif

View file

@ -2307,7 +2307,7 @@ void glob_quit(void* dummy)
reentered = true; reentered = true;
/* Close audio subsystem. */ /* Close audio subsystem. */
sys_close_audio(); /* Will be done by the main program: sys_close_audio(); */
/* Stop main loop. */ /* Stop main loop. */
quit = true; quit = true;
@ -2318,12 +2318,13 @@ void glob_quit(void* dummy)
void glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir); void glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir);
void openit(const char *dirname, const char *filename) void openit(const char *dirname, const char *filename)
{ {
char dirbuf[MAXPDSTRING], *nameptr; char* nameptr;
char* dirbuf = getbytes(MAXPDSTRING);
/* Workaround: If the file resides in the root directory, /* Workaround: If the file resides in the root directory,
add a trailing slash to prevent directory part add a trailing slash to prevent directory part
of the filename from being removed. */ of the filename from being removed -- W.B. */
char ffilename[MAXPDSTRING]; char* ffilename = getbytes(MAXPDSTRING);
ffilename[0] = '/'; ffilename[0] = '/';
ffilename[1] = '\0'; ffilename[1] = '\0';
strcat(ffilename, filename); strcat(ffilename, filename);
@ -2337,6 +2338,10 @@ void openit(const char *dirname, const char *filename)
} }
else else
error("%s: can't open", filename); error("%s: can't open", filename);
/* Clean up. */
freebytes(dirbuf, MAXPDSTRING);
freebytes(ffilename, MAXPDSTRING);
} }
@ -2344,14 +2349,20 @@ void openit(const char *dirname, const char *filename)
extern char* filename; extern char* filename;
char* rb_getcwd(char* buf, ssize_t size) char* rb_getcwd(char* buf, ssize_t size)
{ {
char* end_of_dir = strrchr(filename, '/'); /* Initialize buffer. */
buf[0] = '\0';
/* Check whether buffer may hold enough data. */ /* Search for the last slash. */
if(size < end_of_dir - filename) char* end_of_dir = strrchr(filename, '/');
int dirlen = end_of_dir - filename;
/* Check whether length of directory path is correct.
If not, abort. */
if(size < dirlen || dirlen == 0)
return NULL; return NULL;
/* Copy current working directory to buffer. */ /* Copy current working directory to buffer. */
strncpy(buf, filename, end_of_dir - filename); strncat(buf, filename, dirlen);
return buf; return buf;
} }
@ -2369,7 +2380,7 @@ void glob_initfromgui(void *dummy, t_symbol *s, int argc, t_atom *argv)
(void) argv; (void) argv;
t_namelist *nl; t_namelist *nl;
char cwd[MAXPDSTRING]; char* cwd = getbytes(MAXPDSTRING);
/* Get current working directory. */ /* Get current working directory. */
rb_getcwd(cwd, MAXPDSTRING); rb_getcwd(cwd, MAXPDSTRING);
@ -2377,8 +2388,12 @@ void glob_initfromgui(void *dummy, t_symbol *s, int argc, t_atom *argv)
/* open patches specifies with "-open" args */ /* open patches specifies with "-open" args */
for(nl = sys_openlist; nl; nl = nl->nl_next) for(nl = sys_openlist; nl; nl = nl->nl_next)
openit(cwd, nl->nl_string); openit(cwd, nl->nl_string);
namelist_free(sys_openlist); namelist_free(sys_openlist);
sys_openlist = 0; sys_openlist = 0;
/* Clean up. */
freebytes(cwd, MAXPDSTRING);
} }
/* Fake GUI start. Originally in s_inter.c */ /* Fake GUI start. Originally in s_inter.c */
@ -2390,7 +2405,7 @@ int sys_startgui(const char *guidir)
{ {
unsigned int i; unsigned int i;
t_atom zz[23]; t_atom zz[23];
char cmdbuf[4*MAXPDSTRING]; char* cmdbuf = getbytes(4*MAXPDSTRING);
(void) guidir; (void) guidir;
@ -2398,13 +2413,16 @@ int sys_startgui(const char *guidir)
if(!rb_getcwd(cmdbuf, MAXPDSTRING)) if(!rb_getcwd(cmdbuf, MAXPDSTRING))
strcpy(cmdbuf, "."); strcpy(cmdbuf, ".");
SETSYMBOL(zz, gensym(cmdbuf)); SETSYMBOL(zz, gensym(cmdbuf));
for (i = 1; i < 22; i++) for (i = 1; i < 22; i++)
SETFLOAT(zz + i, defaultfontshit[i-1]); SETFLOAT(zz + i, defaultfontshit[i-1]);
SETFLOAT(zz+22,0); SETFLOAT(zz+22,0);
glob_initfromgui(0, 0, 23, zz); glob_initfromgui(0, 0, 23, zz);
/* Clean up. */
freebytes(cmdbuf, 4*MAXPDSTRING);
return 0; return 0;
} }
@ -2418,11 +2436,14 @@ int sys_getblksize(void)
/* Find library directory and set it. */ /* Find library directory and set it. */
void sys_findlibdir(const char* filename) void sys_findlibdir(const char* filename)
{ {
char sbuf[MAXPDSTRING];
(void) filename; (void) filename;
char* sbuf = getbytes(MAXPDSTRING);
/* Make current working directory the system library directory. */ /* Make current working directory the system library directory. */
rb_getcwd(sbuf, MAXPDSTRING); rb_getcwd(sbuf, MAXPDSTRING);
sys_libdir = gensym(sbuf); sys_libdir = gensym(sbuf);
/* Clean up. */
freebytes(sbuf, MAXPDSTRING);
} }

View file

@ -40,79 +40,34 @@ int sys_verbose;
int sys_noloadbang; int sys_noloadbang;
t_symbol *sys_libdir; t_symbol *sys_libdir;
t_namelist *sys_openlist; t_namelist *sys_openlist;
int sys_nsoundin = 0;
int sys_soundindevlist[MAXAUDIOINDEV]; int sys_soundindevlist[MAXAUDIOINDEV];
int sys_nchin = 0;
int sys_chinlist[MAXAUDIOINDEV]; int sys_chinlist[MAXAUDIOINDEV];
int sys_nsoundout = 1;
int sys_soundoutdevlist[MAXAUDIOOUTDEV]; int sys_soundoutdevlist[MAXAUDIOOUTDEV];
int sys_nchout = 2;
int sys_choutlist[MAXAUDIOOUTDEV]; int sys_choutlist[MAXAUDIOOUTDEV];
static int sys_main_srate = PD_SAMPLERATE;
static int sys_main_advance = PD_SAMPLES_PER_HZ;
/* References for scheduler variables and functions. */ /* References for scheduler variables and functions. */
extern t_time sys_time; extern t_time sys_time;
extern t_time sys_time_per_dsp_tick; extern t_time sys_time_per_dsp_tick;
extern void sched_tick(t_time next_sys_time); extern void sched_tick(t_time next_sys_time);
#define SAMPLES_SIZE 1000 /* LATER consider making this variable. It's now the LCM of all sample
t_sample samples[SAMPLES_SIZE]; rates we expect to see: 32000, 44100, 48000, 88200, 96000. */
#define TIMEUNITPERSEC (32.*441000.)
/* Quit flag. */ /* Quit flag. */
bool quit = false; bool quit = false;
/* Thread IDs. */ /* Thread IDs. */
unsigned int core_thread_id;
unsigned int gui_thread_id; unsigned int gui_thread_id;
unsigned int time_thread_id; unsigned int time_thread_id;
/* Stacks for threads. */ /* Stacks for threads. */
#define STACK_SIZE 16384 #define STACK_SIZE 16384
uint32_t core_stack[STACK_SIZE / sizeof(uint32_t)];
uint32_t gui_stack[STACK_SIZE / sizeof(uint32_t)]; uint32_t gui_stack[STACK_SIZE / sizeof(uint32_t)];
uint32_t time_stack[256 / sizeof(uint32_t)]; uint32_t time_stack[256 / sizeof(uint32_t)];
/* Core thread, scheduler. */
void core_thread(void)
{
/* struct datagram ping; */
/* LATER consider making this variable. It's now the LCM of all sample
rates we expect to see: 32000, 44100, 48000, 88200, 96000. */
#define TIMEUNITPERSEC (32.*441000.)
sys_time = 0;
sys_time_per_dsp_tick = (TIMEUNITPERSEC) *
((double)sys_schedblocksize) / sys_dacsr;
/* Main loop */
while(!quit)
{
#if 0
/* Wait for request. */
while(!RECEIVE_TO_CORE(&ping))
rb->yield();
if(memcmp("Ping!", ping.data, ping.size) == 0)
{
SEND_FROM_CORE("Pong!");
break;
}
#endif
/* Use sys_send_dacs() function as timer. */
if(sys_send_dacs() != SENDDACS_NO)
sched_tick(sys_time + sys_time_per_dsp_tick);
rb->sleep(1);
}
rb->thread_exit();
}
/* GUI thread */ /* GUI thread */
void gui_thread(void) void gui_thread(void)
{ {
@ -138,6 +93,8 @@ void gui_thread(void)
break; break;
} }
#endif #endif
if(rb->button_get(false) == BUTTON_OFF)
quit = true;
rb->sleep(1); rb->sleep(1);
} }
@ -168,8 +125,13 @@ enum plugin_status plugin_start(const void* parameter)
size_t mem_size; size_t mem_size;
void* mem_pool; void* mem_pool;
/* Get the file name. */ /* Get the file name; check whether parameter contains no file name. */
filename = (char*) parameter; filename = (char*) parameter;
if(strlen(filename) == 0)
{
rb->splash(HZ, "Play a .pd file!");
return PLUGIN_ERROR;
}
/* Allocate memory; check it's size; add to the pool. */ /* Allocate memory; check it's size; add to the pool. */
mem_pool = rb->plugin_get_audio_buffer(&mem_size); mem_pool = rb->plugin_get_audio_buffer(&mem_size);
@ -186,23 +148,31 @@ enum plugin_status plugin_start(const void* parameter)
/* Initialize Pure Data, as does sys_main in s_main.c */ /* Initialize Pure Data, as does sys_main in s_main.c */
pd_init(); pd_init();
/* Set audio API. */
sys_set_audio_api(API_ROCKBOX);
/* Initialize audio subsystem. */
sys_open_audio(0, /* No sound input yet */
sys_soundindevlist,
0, /* No sound input yet */
sys_chinlist,
1, /* One sound output device */
sys_soundoutdevlist,
-1, /* Use the default amount (2) of channels */
sys_choutlist,
PD_SAMPLERATE, /* Sample rate */
DEFAULTADVANCE, /* Scheduler advance */
1 /* Enable */);
/* Add the directory the called .pd resides in to lib directories. */ /* Add the directory the called .pd resides in to lib directories. */
sys_findlibdir(filename); sys_findlibdir(filename);
/* Open the parameter file. */ /* Open the parameter file. */
sys_openlist = namelist_append(sys_openlist, filename); sys_openlist = namelist_append(sys_openlist, filename);
/* Set audio API. */
sys_set_audio_api(API_ROCKBOX);
/* Fake a GUI start. */ /* Fake a GUI start. */
sys_startgui(NULL); sys_startgui(NULL);
/* Initialize audio subsystem. */
sys_open_audio(sys_nsoundin, sys_soundindevlist, sys_nchin, sys_chinlist,
sys_nsoundout, sys_soundoutdevlist, sys_nchout, sys_choutlist,
sys_main_srate, sys_main_advance, 1);
/* Start threads. */ /* Start threads. */
time_thread_id = time_thread_id =
rb->create_thread(&time_thread, rb->create_thread(&time_thread,
@ -212,15 +182,7 @@ enum plugin_status plugin_start(const void* parameter)
"PD running time" "PD running time"
IF_PRIO(, PRIORITY_REALTIME) IF_PRIO(, PRIORITY_REALTIME)
IF_COP(, COP)); IF_COP(, COP));
core_thread_id =
rb->create_thread(&core_thread,
core_stack,
sizeof(core_stack),
0, /* FIXME Which flags? */
"PD core"
IF_PRIO(, MAX(PRIORITY_USER_INTERFACE / 2,
PRIORITY_REALTIME + 1))
IF_COP(, COP));
gui_thread_id = gui_thread_id =
rb->create_thread(&gui_thread, rb->create_thread(&gui_thread,
gui_stack, gui_stack,
@ -231,18 +193,33 @@ enum plugin_status plugin_start(const void* parameter)
IF_COP(, CPU)); IF_COP(, CPU));
/* If having an error creating threads, bail out. */ /* If having an error creating threads, bail out. */
if(core_thread_id == 0 || gui_thread_id == 0) if(time_thread_id == 0 || gui_thread_id == 0)
return PLUGIN_ERROR; return PLUGIN_ERROR;
/* Wait for quit flag. */ /* Initialize scheduler time variables. */
sys_time = 0;
sys_time_per_dsp_tick = (TIMEUNITPERSEC) *
((double) sys_schedblocksize) / sys_dacsr;
/* Main loop. */
while(!quit) while(!quit)
yield(); {
/* Use sys_send_dacs() function as timer. */
while(sys_send_dacs() != SENDDACS_NO)
sched_tick(sys_time + sys_time_per_dsp_tick);
/* Sleep to the next time slice. */
rb->sleep(1);
}
/* Wait for threads to complete. */ /* Wait for threads to complete. */
rb->thread_wait(gui_thread_id); rb->thread_wait(gui_thread_id);
rb->thread_wait(core_thread_id);
rb->thread_wait(time_thread_id); rb->thread_wait(time_thread_id);
/* Close audio subsystem. */
sys_close_audio();
/* Destroy net. */ /* Destroy net. */
net_destroy(); net_destroy();

View file

@ -37,21 +37,21 @@
/* Audio declarations. */ /* Audio declarations. */
#define PD_SAMPLERATE 32000 #define PD_SAMPLERATE 22050
#define PD_SAMPLES_QUOT (PD_SAMPLERATE / HZ) #define PD_SAMPLES_PER_HZ ((PD_SAMPLERATE / HZ) + \
#define PD_SAMPLES_REM (PD_SAMPLERATE % HZ) (PD_SAMPLERATE % HZ > 0 ? 1 : 0))
#if PD_SAMPLES_REM == 0 #define PD_OUT_CHANNELS 2
#define PD_SAMPLES_PER_HZ (PD_SAMPLES_QUOT)
#else
#define PD_SAMPLES_PER_HZ (PD_SAMPLES_QUOT + 1)
#endif
/* Audio data types. */ /* Audio buffer part. Contains data for one HZ period. */
#define PD_AUDIO_BLOCK_SIZE PD_SAMPLES_PER_HZ #ifdef SIMULATOR
struct pdbox_audio_block #define AUDIOBUFSIZE (PD_SAMPLES_PER_HZ * PD_OUT_CHANNELS * 4)
#else
#define AUDIOBUFSIZE (PD_SAMPLES_PER_HZ * PD_OUT_CHANNELS)
#endif
struct audio_buffer
{ {
int16_t data[AUDIOBUFSIZE];
unsigned int fill; unsigned int fill;
int32_t data[PD_AUDIO_BLOCK_SIZE];
}; };
@ -139,6 +139,10 @@ void pd_init(void);
/* Redefinitons of ANSI C functions. */ /* Redefinitons of ANSI C functions. */
#include "lib/wrappers.h" #include "lib/wrappers.h"
#define strncmp rb->strncmp
#define atoi rb->atoi
#define write rb->write
#define strncat rb_strncat #define strncat rb_strncat
#define floor rb_floor #define floor rb_floor
#define atof rb_atof #define atof rb_atof