Midiplay plugin ehancements

- Improved robustness
 - Improved sound quality
 - Use mixer and DSP

Patch by Igor Poretsky

Change-Id: I6fa617158cbaa53ae842295cdbdbe3a478e49ded
This commit is contained in:
Solomon Peachy 2019-08-04 16:58:20 -04:00
parent eea5bfc9ae
commit ed724fecb1
7 changed files with 232 additions and 115 deletions

View file

@ -66,6 +66,8 @@ static struct GWaveform * loadWaveform(int file)
rb->memset(wav, 0, sizeof(struct GWaveform)); rb->memset(wav, 0, sizeof(struct GWaveform));
wav->name=readData(file, 7); wav->name=readData(file, 7);
if (!wav->name)
return NULL;
/* printf("\nWAVE NAME = [%s]", wav->name); */ /* printf("\nWAVE NAME = [%s]", wav->name); */
wav->fractions=readChar(file); wav->fractions=readChar(file);
wav->wavSize=readDWord(file); wav->wavSize=readDWord(file);
@ -81,7 +83,11 @@ static struct GWaveform * loadWaveform(int file)
wav->balance=readChar(file); wav->balance=readChar(file);
wav->envRate=readData(file, 6); wav->envRate=readData(file, 6);
if (!wav->envRate)
return NULL;
wav->envOffset=readData(file, 6); wav->envOffset=readData(file, 6);
if (!wav->envOffset)
return NULL;
wav->tremSweep=readChar(file); wav->tremSweep=readChar(file);
wav->tremRate=readChar(file); wav->tremRate=readChar(file);
@ -95,7 +101,11 @@ static struct GWaveform * loadWaveform(int file)
wav->scaleFactor=readWord(file); wav->scaleFactor=readWord(file);
/* printf("\nScaleFreq = %d ScaleFactor = %d RootFreq = %d", wav->scaleFreq, wav->scaleFactor, wav->rootFreq); */ /* printf("\nScaleFreq = %d ScaleFactor = %d RootFreq = %d", wav->scaleFreq, wav->scaleFactor, wav->rootFreq); */
wav->res=readData(file, 36); wav->res=readData(file, 36);
if (!wav->res)
return NULL;
wav->data=readData(file, wav->wavSize); wav->data=readData(file, wav->wavSize);
if (!wav->data)
return NULL;
wav->numSamples = wav->wavSize / 2; wav->numSamples = wav->wavSize / 2;
wav->startLoop = wav->startLoop >> 1; wav->startLoop = wav->startLoop >> 1;
@ -166,7 +176,10 @@ static int selectWaveform(struct GPatch * pat, int midiNote)
struct GPatch * gusload(char * filename) struct GPatch * gusload(char * filename)
{ {
struct GPatch * gp = (struct GPatch *)malloc(sizeof(struct GPatch)); struct GPatch * gp = (struct GPatch *)malloc(sizeof(struct GPatch));
if (gp)
rb->memset(gp, 0, sizeof(struct GPatch)); rb->memset(gp, 0, sizeof(struct GPatch));
else return NULL;
int file = rb->open(filename, O_RDONLY); int file = rb->open(filename, O_RDONLY);
@ -179,8 +192,23 @@ struct GPatch * gusload(char * filename)
} }
gp->header=readData(file, 12); gp->header=readData(file, 12);
if (!gp->header)
{
rb->close(file);
return NULL;
}
gp->gravisid=readData(file, 10); gp->gravisid=readData(file, 10);
if (!gp->gravisid)
{
rb->close(file);
return NULL;
}
gp->desc=readData(file, 60); gp->desc=readData(file, 60);
if (!gp->desc)
{
rb->close(file);
return NULL;
}
gp->inst=readChar(file); gp->inst=readChar(file);
gp->voc=readChar(file); gp->voc=readChar(file);
gp->chan=readChar(file); gp->chan=readChar(file);
@ -188,28 +216,52 @@ struct GPatch * gusload(char * filename)
gp->vol=readWord(file); gp->vol=readWord(file);
gp->datSize=readDWord(file); gp->datSize=readDWord(file);
gp->res=readData(file, 36); gp->res=readData(file, 36);
if (!gp->res)
{
rb->close(file);
return NULL;
}
gp->instrID=readWord(file); gp->instrID=readWord(file);
gp->instrName=readData(file,16); gp->instrName=readData(file,16);
if (!gp->instrName)
{
rb->close(file);
return NULL;
}
gp->instrSize=readDWord(file); gp->instrSize=readDWord(file);
gp->layers=readChar(file); gp->layers=readChar(file);
gp->instrRes=readData(file,40); gp->instrRes=readData(file,40);
if (!gp->instrRes)
{
rb->close(file);
return NULL;
}
gp->layerDup=readChar(file); gp->layerDup=readChar(file);
gp->layerID=readChar(file); gp->layerID=readChar(file);
gp->layerSize=readDWord(file); gp->layerSize=readDWord(file);
gp->numWaves=readChar(file); gp->numWaves=readChar(file);
gp->layerRes=readData(file,40); gp->layerRes=readData(file,40);
if (!gp->layerRes)
{
rb->close(file);
return NULL;
}
/* printf("\nFILE: %s", filename); */ /* printf("\nFILE: %s", filename); */
/* printf("\nlayerSamples=%d", gp->numWaves); */ /* printf("\nlayerSamples=%d", gp->numWaves); */
int a=0; int a=0;
for(a=0; a<gp->numWaves; a++) for(a=0; a<gp->numWaves; a++)
{
gp->waveforms[a] = loadWaveform(file); gp->waveforms[a] = loadWaveform(file);
if (!gp->waveforms[a])
{
rb->close(file);
return NULL;
}
}
/* printf("\nPrecomputing note table"); */ /* printf("\nPrecomputing note table"); */

View file

@ -106,6 +106,11 @@ struct MIDIfile * loadFile(const char * filename)
if(id == ID_MTRK) if(id == ID_MTRK)
{ {
mfload->tracks[track] = readTrack(file); mfload->tracks[track] = readTrack(file);
if (!mfload->tracks[track])
{
rb->close(file);
return NULL;
}
track++; track++;
} else } else
{ {
@ -125,7 +130,7 @@ struct MIDIfile * loadFile(const char * filename)
* and then track 2 starts loading */ * and then track 2 starts loading */
int rStatus = 0; int rStatus = 0;
/* Returns 0 if done, 1 if keep going */ /* Returns 0 if done, 1 if keep going and -1 in case of error */
static int readEvent(int file, void * dest) static int readEvent(int file, void * dest)
{ {
struct Event dummy; struct Event dummy;
@ -152,6 +157,8 @@ static int readEvent(int file, void * dest)
{ {
/* Null-terminate for text events */ /* Null-terminate for text events */
ev->evData = malloc(ev->len+1); /* Extra byte for the null termination */ ev->evData = malloc(ev->len+1); /* Extra byte for the null termination */
if (!ev->evData)
return -1;
rb->read(file, ev->evData, ev->len); rb->read(file, ev->evData, ev->len);
ev->evData[ev->len] = 0; ev->evData[ev->len] = 0;
@ -272,27 +279,35 @@ struct Track * readTrack(int file)
int pos = rb->lseek(file, 0, SEEK_CUR); int pos = rb->lseek(file, 0, SEEK_CUR);
while(readEvent(file, NULL)) /* Memory saving technique */ int evstat;
while ((evstat = readEvent(file, NULL)) > 0) /* Memory saving technique */
numEvents++; /* Attempt to read in events, count how many */ numEvents++; /* Attempt to read in events, count how many */
/* THEN allocate memory and read them in */ /* THEN allocate memory and read them in */
if (evstat < 0)
return NULL;
rb->lseek(file, pos, SEEK_SET); rb->lseek(file, pos, SEEK_SET);
int trackSize = (numEvents+1) * sizeof(struct Event); int trackSize = (numEvents+1) * sizeof(struct Event);
void * dataPtr = malloc(trackSize); void * dataPtr = malloc(trackSize);
if (!dataPtr)
return NULL;
trk->dataBlock = dataPtr; trk->dataBlock = dataPtr;
numEvents=0; numEvents=0;
while(readEvent(file, dataPtr)) while ((evstat = readEvent(file, dataPtr)) > 0)
{ {
if(trackSize < dataPtr-trk->dataBlock) if(trackSize < dataPtr-trk->dataBlock)
{ {
midi_debug("Track parser memory out of bounds"); midi_debug("Track parser memory out of bounds");
exit(1); return NULL;
} }
dataPtr+=sizeof(struct Event); dataPtr+=sizeof(struct Event);
numEvents++; numEvents++;
} }
if (evstat < 0)
return NULL;
trk->numEvents = numEvents; trk->numEvents = numEvents;
return trk; return trk;

View file

@ -348,6 +348,10 @@
#define SYNC #define SYNC
#endif #endif
#ifndef ALIGNED_ATTR
#define ALIGNED_ATTR(x) __attribute__((aligned(x)))
#endif
struct MIDIfile * mf IBSS_ATTR; struct MIDIfile * mf IBSS_ATTR;
int number_of_samples IBSS_ATTR; /* the number of samples in the current tick */ int number_of_samples IBSS_ATTR; /* the number of samples in the current tick */
@ -355,52 +359,79 @@ int playing_time IBSS_ATTR; /* How many seconds into the file have we been play
int samples_this_second IBSS_ATTR; /* How many samples produced during this second so far? */ int samples_this_second IBSS_ATTR; /* How many samples produced during this second so far? */
long bpm IBSS_ATTR; long bpm IBSS_ATTR;
int32_t gmbuf[BUF_SIZE*NBUF]; #ifndef SYNC
static unsigned int samples_in_buf; /* Small silence clip. ~5.80ms @ 44.1kHz */
static int32_t silence[256] ALIGNED_ATTR(4) = { 0 };
bool midi_end = false; static int32_t gmbuf[BUF_SIZE * NBUF] ALIGNED_ATTR(4);
bool quit = false;
bool swap = false; static volatile bool swap = false;
bool lastswap = true; static volatile bool lastswap = true;
#else
static int32_t gmbuf[BUF_SIZE] ALIGNED_ATTR(4);
#endif
static volatile size_t samples_in_buf;
static volatile bool midi_end = false;
static volatile bool quit = false;
static int32_t samp_buf[MAX_SAMPLES * 2] IBSS_ATTR;
static struct dsp_config *dsp;
static struct dsp_buffer src;
static struct dsp_buffer dst;
static inline void synthbuf(void) static inline void synthbuf(void)
{ {
int32_t *outptr; int32_t *outptr;
int i = BUF_SIZE; int available = BUF_SIZE;
#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
rb->cpu_boost(true);
#endif
#ifndef SYNC #ifndef SYNC
if (lastswap == swap) if (lastswap == swap)
return; return;
lastswap = swap;
outptr = (swap ? gmbuf : gmbuf+BUF_SIZE); outptr = (swap ? gmbuf : gmbuf+BUF_SIZE);
#else #else
outptr = gmbuf; outptr = gmbuf;
#endif #endif
if (midi_end) {
samples_in_buf = 0;
return;
}
/* synth samples for as many whole ticks as we can fit in the buffer */ #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
for (; i >= number_of_samples; i -= number_of_samples) rb->cpu_boost(true);
{
synthSamples((int32_t*)outptr, number_of_samples);
outptr += number_of_samples;
#ifndef SYNC
/* synthbuf is called in interrupt context is SYNC is defined so it cannot yield
that bug causing the sim to crach when not using SYNC should really be fixed */
rb->yield();
#endif #endif
if (tick() == 0) /* synth samples for as many whole ticks as we can fit in the buffer */
while (available > 0)
{
if ((dst.remcount <= 0) && !midi_end)
{
int nsamples = synthSamples(samp_buf, number_of_samples);
if (nsamples < number_of_samples)
number_of_samples -= nsamples;
else if (!tick())
midi_end = true; /* no more midi data to play */ midi_end = true; /* no more midi data to play */
src.remcount = nsamples;
src.pin[0] = &samp_buf[0];
src.pin[1] = &samp_buf[1];
src.proc_mask = 0;
}
dst.remcount = 0;
dst.bufcount = available;
dst.p16out = (int16_t *)outptr;
rb->dsp_process(dsp, &src, &dst);
if (dst.remcount > 0)
{
outptr += dst.remcount;
available -= dst.remcount;
}
else if (midi_end)
break;
} }
/* how many samples did we write to the buffer? */ /* how many samples did we write to the buffer? */
samples_in_buf = BUF_SIZE-i; samples_in_buf = BUF_SIZE - available;
#ifndef SYNC
lastswap = swap;
#endif
#if defined(HAVE_ADJUSTABLE_CPU_FREQ) #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
rb->cpu_boost(false); rb->cpu_boost(false);
#endif #endif
@ -409,26 +440,27 @@ static inline void synthbuf(void)
static void get_more(const void** start, size_t* size) static void get_more(const void** start, size_t* size)
{ {
#ifndef SYNC #ifndef SYNC
if(lastswap != swap) swap = !swap;
if(lastswap == swap)
{ {
midi_debug("Buffer miss!"); /* Comment out the midi_debug to make missses less noticable. */ *start = silence;
*size = sizeof(silence);
swap = !swap;
return;
} }
else if (samples_in_buf)
*start = swap ? (gmbuf + BUF_SIZE) : gmbuf;
#else #else
synthbuf(); /* For some reason midiplayer crashes when an update is forced */ synthbuf(); /* For some reason midiplayer crashes when an update is forced */
#endif if (samples_in_buf)
*size = samples_in_buf*sizeof(int32_t);
#ifndef SYNC
*start = swap ? gmbuf : gmbuf + BUF_SIZE;
swap = !swap;
#else
*start = gmbuf; *start = gmbuf;
#endif #endif
if (samples_in_buf==0) { else
{
*start = NULL; *start = NULL;
quit = true; /* this was the last buffer to play */ quit = true; /* this was the last buffer to play */
} }
*size = samples_in_buf*sizeof(int32_t);
} }
static int midimain(const void * filename) static int midimain(const void * filename)
@ -460,13 +492,26 @@ static int midimain(const void * filename)
return -1; return -1;
} }
rb->talk_force_shutup();
rb->pcm_play_stop(); rb->pcm_play_stop();
#if INPUT_SRC_CAPS != 0 #if INPUT_SRC_CAPS != 0
/* Select playback */ /* Select playback */
rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
rb->audio_set_output_source(AUDIO_SRC_PLAYBACK); rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
#endif #endif
rb->pcm_set_frequency(SAMPLE_RATE); /* 44100 22050 11025 */
dst.remcount = 0;
dsp = rb->dsp_get_config(CODEC_IDX_AUDIO);
rb->dsp_configure(dsp, DSP_RESET, 0);
rb->dsp_configure(dsp, DSP_FLUSH, 0);
rb->dsp_configure(dsp, DSP_SET_OUT_FREQUENCY, rb->mixer_get_frequency());
#ifdef HAVE_PITCHCONTROL
rb->sound_set_pitch(PITCH_SPEED_100);
rb->dsp_set_timestretch(PITCH_SPEED_100);
#endif
rb->dsp_configure(dsp, DSP_SET_SAMPLE_DEPTH, 22);
rb->dsp_configure(dsp, DSP_SET_FREQUENCY, SAMPLE_RATE); /* 44100 22050 11025 */
rb->dsp_configure(dsp, DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
/* /*
* tick() will do one MIDI clock tick. Then, there's a loop here that * tick() will do one MIDI clock tick. Then, there's a loop here that
@ -501,8 +546,12 @@ static int midimain(const void * filename)
playing_time = 0; playing_time = 0;
samples_this_second = 0; samples_this_second = 0;
#ifndef SYNC
synthbuf(); synthbuf();
rb->pcm_play_data(&get_more, NULL, NULL, 0); #endif
rb->pcmbuf_fade(false, true);
rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
while (!quit) while (!quit)
{ {
@ -547,7 +596,9 @@ static int midimain(const void * filename)
{ {
/* Rewinding is tricky. Basically start the file over */ /* Rewinding is tricky. Basically start the file over */
/* but run through the tracks without the synth running */ /* but run through the tracks without the synth running */
rb->pcm_play_stop(); rb->mixer_channel_stop(PCM_MIXER_CHAN_PLAYBACK);
rb->dsp_configure(dsp, DSP_FLUSH, 0);
dst.remcount = 0;
#if defined(HAVE_ADJUSTABLE_CPU_FREQ) #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
rb->cpu_boost(true); rb->cpu_boost(true);
#endif #endif
@ -555,39 +606,45 @@ static int midimain(const void * filename)
#if defined(HAVE_ADJUSTABLE_CPU_FREQ) #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
rb->cpu_boost(false); rb->cpu_boost(false);
#endif #endif
#ifndef SYNC
lastswap = !swap; lastswap = !swap;
synthbuf(); synthbuf();
#endif
midi_debug("Rewind to %d:%02d\n", playing_time/60, playing_time%60); midi_debug("Rewind to %d:%02d\n", playing_time/60, playing_time%60);
if (is_playing) if (is_playing)
rb->pcm_play_data(&get_more, NULL, NULL, 0); rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
break; break;
} }
case MIDI_FFWD: case MIDI_FFWD:
{ {
rb->pcm_play_stop(); rb->mixer_channel_stop(PCM_MIXER_CHAN_PLAYBACK);
rb->dsp_configure(dsp, DSP_FLUSH, 0);
dst.remcount = 0;
#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
rb->cpu_boost(true);
#endif
seekForward(5); seekForward(5);
#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
rb->cpu_boost(false);
#endif
#ifndef SYNC
lastswap = !swap; lastswap = !swap;
synthbuf(); synthbuf();
#endif
midi_debug("Skip to %d:%02d\n", playing_time/60, playing_time%60); midi_debug("Skip to %d:%02d\n", playing_time/60, playing_time%60);
if (is_playing) if (is_playing)
rb->pcm_play_data(&get_more, NULL, NULL, 0); rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
break; break;
} }
case MIDI_PLAYPAUSE: case MIDI_PLAYPAUSE:
{ {
if (is_playing) is_playing = !is_playing;
{ midi_debug("%s %d:%02d\n",
midi_debug("Paused at %d:%02d\n", playing_time/60, playing_time%60); is_playing ? "Playing from" : "Paused at",
is_playing = false; playing_time/60, playing_time%60);
rb->pcm_play_stop(); rb->mixer_channel_play_pause(PCM_MIXER_CHAN_PLAYBACK, is_playing);
} else
{
midi_debug("Playing from %d:%02d\n", playing_time/60, playing_time%60);
is_playing = true;
rb->pcm_play_data(&get_more, NULL, NULL, 0);
}
break; break;
} }
@ -598,6 +655,10 @@ static int midimain(const void * filename)
quit = true; quit = true;
} }
} }
rb->pcmbuf_fade(false, false);
rb->mixer_channel_stop(PCM_MIXER_CHAN_PLAYBACK);
return 0; return 0;
} }
@ -625,9 +686,6 @@ enum plugin_status plugin_start(const void* parameter)
rb->profstop(); rb->profstop();
#endif #endif
rb->pcm_play_stop();
rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
rb->splash(HZ, "FINISHED PLAYING"); rb->splash(HZ, "FINISHED PLAYING");
if (retval == -1) if (retval == -1)

View file

@ -39,37 +39,40 @@ struct SynthObject voices[MAX_VOICES] IBSS_ATTR;
static void *alloc(int size) static void *alloc(int size)
{ {
static char *offset = NULL; static char *offset[2] = {NULL};
static size_t totalSize = 0; static size_t totalSize[2] = {0};
char *ret; char *ret;
int n;
int remainder = size % 4; int remainder = size % 4;
size = size + 4-remainder; size = size + 4-remainder;
if (offset == NULL) if (offset[0] == NULL)
{ {
offset = rb->plugin_get_audio_buffer(&totalSize); offset[0] = rb->plugin_get_buffer(&totalSize[0]);
} }
if (size + 4 > (int)totalSize) if (offset[1] == NULL)
{
offset[1] = rb->plugin_get_audio_buffer(&totalSize[1]);
}
n = (totalSize[0] > totalSize[1]) ? 1 : 0;
if (size + 4 > (int)totalSize[n])
n ^= 1;
if (size + 4 > (int)totalSize[n])
{ {
midi_debug("Out of Memory"); midi_debug("Out of Memory");
midi_debug("MALLOC BARF");
midi_debug("MALLOC BARF");
midi_debug("MALLOC BARF");
midi_debug("MALLOC BARF");
midi_debug("MALLOC BARF");
/* We've made our point. */
return NULL; return NULL;
} }
ret = offset + 4; ret = offset[n] + 4;
*((unsigned int *)offset) = size; *((unsigned int *)offset[n]) = size;
offset += size + 4; offset[n] += size + 4;
totalSize -= size + 4; totalSize[n] -= size + 4;
return ret; return ret;
} }
@ -117,6 +120,7 @@ unsigned char readChar(int file)
void * readData(int file, int len) void * readData(int file, int len)
{ {
void * dat = malloc(len); void * dat = malloc(len);
if (dat)
rb->read(file, dat, len); rb->read(file, dat, len);
return dat; return dat;
} }

View file

@ -25,14 +25,11 @@
#define BUF_SIZE 16384 /* 64 kB output buffers */ #define BUF_SIZE 16384 /* 64 kB output buffers */
#define NBUF 2 #define NBUF 2
#define MAX_SAMPLES 512
#ifndef SIMULATOR #ifndef SIMULATOR
#if (HW_SAMPR_CAPS & SAMPR_CAP_22) /* use 22050Hz if we can */
#define SAMPLE_RATE SAMPR_22 /* 22050 */
#else
#define SAMPLE_RATE SAMPR_44 /* 44100 */ #define SAMPLE_RATE SAMPR_44 /* 44100 */
#endif
/* Some of the pp based targets can't handle too many voices /* Some of the pp based targets can't handle too many voices
mainly because they have to use 44100Hz sample rate, this could be mainly because they have to use 44100Hz sample rate, this could be

View file

@ -300,7 +300,8 @@ static inline void synthVoice(struct SynthObject * so, int32_t * out, unsigned i
s1 = so->decay; s1 = so->decay;
s2 = s1 * pan; s2 = s1 * pan;
s1 = (s1 << 7) -s2; s1 = (s1 << 7) -s2;
*(out++) += ((s1 << 9) & 0xFFFF0000) | ((s2 >> 7) &0xFFFF); *(out++) += s1;
*(out++) += s2;
continue; continue;
} }
} else /* OK to advance voice */ } else /* OK to advance voice */
@ -431,7 +432,8 @@ static inline void synthVoice(struct SynthObject * so, int32_t * out, unsigned i
s2 = s1 * pan; s2 = s1 * pan;
s1 = (s1 << 7) - s2; s1 = (s1 << 7) - s2;
*(out++) += ((s1 << 9) & 0xFFFF0000) | ((s2 >> 7) &0xFFFF); *(out++) += s1;
*(out++) += s2;
} }
/* store these again */ /* store these again */
@ -441,40 +443,29 @@ static inline void synthVoice(struct SynthObject * so, int32_t * out, unsigned i
return; return;
} }
/* buffer to hold all the samples for the current tick, this is a hack
neccesary for coldfire targets as pcm_play_data uses the dma which cannot
access iram */
int32_t samp_buf[512] IBSS_ATTR;
/* synth num_samples samples and write them to the */ /* synth num_samples samples and write them to the */
/* buffer pointed to by buf_ptr */ /* buffer pointed to by buf_ptr */
void synthSamples(int32_t *buf_ptr, unsigned int num_samples) ICODE_ATTR; size_t synthSamples(int32_t *buf_ptr, size_t num_samples) ICODE_ATTR;
void synthSamples(int32_t *buf_ptr, unsigned int num_samples) size_t synthSamples(int32_t *buf_ptr, size_t num_samples)
{ {
if (UNLIKELY(num_samples > 512)) unsigned int i;
DEBUGF("num_samples is too big!\n");
else
{
int i;
struct SynthObject *voicept; struct SynthObject *voicept;
size_t nsamples = MIN(num_samples, MAX_SAMPLES);
rb->memset(samp_buf, 0, num_samples*4); rb->memset(buf_ptr, 0, nsamples * 2 * sizeof(int32_t));
for(i=0; i < MAX_VOICES; i++) for(i=0; i < MAX_VOICES; i++)
{ {
voicept=&voices[i]; voicept=&voices[i];
if(voicept->isUsed) if(voicept->isUsed)
{ {
synthVoice(voicept, samp_buf, num_samples); synthVoice(voicept, buf_ptr, nsamples);
} }
} }
rb->memcpy(buf_ptr, samp_buf, num_samples*4);
}
/* TODO: Automatic Gain Control, anyone? */ /* TODO: Automatic Gain Control, anyone? */
/* Or, should this be implemented on the DSP's output volume instead? */ /* Or, should this be implemented on the DSP's output volume instead? */
return; /* No more ghetto lowpass filter. Linear interpolation works well. */ return nsamples; /* No more ghetto lowpass filter. Linear interpolation works well. */
} }

View file

@ -20,7 +20,7 @@
****************************************************************************/ ****************************************************************************/
int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig); int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig);
void setPoint(struct SynthObject * so, int pt); void setPoint(struct SynthObject * so, int pt);
void synthSamples(int32_t *buf_ptr, unsigned int num_samples); size_t synthSamples(int32_t *buf_ptr, size_t num_samples);
void resetControllers(void); void resetControllers(void);