// The new function using fixed point multiplication QPolygon MapMatrix::map(const QPolygon &a) const { int size = a.size(); int64_t fx; int64_t fy; int32_t curx; int32_t cury; int32_t lastx = 0; int32_t lasty = 0; QPolygon p; for( int i = 0; i < size; i++ ) { a.point(i, &curx, &cury); fx = itofp24p8( curx ); fy = itofp24p8( cury ); // some cheating involved; multiplication with the "wrong" macro // after "left shifting" the "m" value in createMatrix curx = fp24p8toi( mulfp8p24(m11,fx) + mulfp8p24(m21,fy) + dx); cury = fp24p8toi( mulfp8p24(m22,fy) + mulfp8p24(m12,fx) + dy); if ( (i==0) | ( ((curx - lastx) | (cury - lasty)) != 0) ) { p.append(QPoint(curx, cury)); lastx = curx; lasty = cury; } } return p; }
QPoint MapMatrix::map(const QPoint& p) const { int64_t fx = itofp24p8( p.x() ); int64_t fy = itofp24p8( p.y() ); // some cheating involved; multiplication with the "wrong" macro // after "left shifting" the "m" value in createMatrix return QPoint( fp24p8toi( mulfp8p24(m11,fx) + mulfp8p24(m21,fy) + dx), fp24p8toi( mulfp8p24(m22,fy) + mulfp8p24(m12,fx) + dy) ); }
void execute(MachineTable *mt, void *void_info) { ssynths *info = (ssynths *)void_info; int x; fp16p16_t wa_step, amplitude, am_step; int bfrsize, index, elimit, envelope, period; sline *line; SignalPointer *s = NULL; SignalPointer *sig = NULL; void **in = NULL; MidiEvent *mev = NULL; s = mt->get_input_signal(mt, "midi"); if(s == NULL) return; in = (void **)mt->get_signal_buffer(s); sig = mt->get_output_signal(mt, "Mono"); if(sig == NULL) return; bfrsize = mt->get_signal_samples(sig); //thing that change index = info->index; wa_step = info->wa_step; amplitude = info->amplitude; am_step = info->am_step; elimit = info->elimit; envelope = info->envelope; period = info->period; float Fs = (float)mt->get_signal_frequency(sig); float timeSlice_f = ((float)SSYNTH_TABLE_LENGTH) / Fs; fp16p16_t timeSlice = ftofp16p16(timeSlice_f); FTYPE *data = (FTYPE *)mt->get_signal_buffer(sig); fp8p24_t volume = ftofp8p24(info->volume); line = &(info->line); for(x = 0; x < bfrsize; x++) { int k; mev = in[x]; if(mev != NULL) { int note; if( ((mev->data[0] & 0xf0) == MIDI_NOTE_ON) && ((mev->data[0] & 0x0f) == info->midi_channel) ) { line->note = mev->data[1]; fp8p24_t velocity; int *tmpv = &velocity; *tmpv = ((int)mev->data[2]) << 16; line->attack = ftofp16p16(0.05); line->decay = ftofp16p16(0.1); line->sustain = ftofp16p16(0.5); line->release = ftofp16p16(0.1); line->volume = mulfp8p24(volume, velocity); line->hold_on = 1; note = line->note; elimit = fp16p16toi(mulfp16p16(line->attack, itofp16p16(4000))); am_step = divfp16p16(line->volume, itofp16p16(elimit)); amplitude = itofp16p16(0); wa_step = mulfp16p16( timeSlice, note_table[note]); envelope = 0; period = (int)((float)(Fs / fp16p16tof(note_table[note]))); info->decay = line->decay; info->sustain = line->sustain; info->release = line->release; } if( ((mev->data[0] & 0xf0) == MIDI_NOTE_OFF) && ((mev->data[0] & 0x0f) == info->midi_channel) && ((mev->data[1] == line->note)) ) { line->hold_on = 0; } } k = index % period; fp8p24_t out; fp16p16_t table_index_f = mulfp16p16(itofp16p16(k), wa_step); int table_index = fp16p16toi(table_index_f); table_index = table_index % SSYNTH_TABLE_LENGTH; out = mulfp8p24(amplitude, ssynth_table[table_index]); // table_index = index; // index = (index + 1) % SSYNTH_TABLE_LENGTH; // out = ssynth_table[x * d];//table_index]; #ifdef __SATAN_USES_FXP data[x] = out; #else data[x] = fp8p24tof(out); #endif amplitude += am_step; /* Hold Comment A: * This is a special case for sustain (hold) * when the MIDI note off message is received * the hold flag is set to zero, when that has * happened and the envelope has reached 1 * the elimit is set to 1 and envelope to two * which will cause the execution to enter * the following if()-block (Hold Comment B) */ if((envelope == 2) && (line->hold_on == 0)) { envelope = 3; elimit = 0; } /* Hold Comment B: * This block is reached before the envelope is "sustain", * or after hold_on has been set to zero, se comment A. */ if((envelope != 2) && (elimit-- == 0)) { // new envelope mode envelope++; switch(envelope) { case 1: // Decay elimit = fp8p24toi(mulfp16p16(itofp16p16(4000), info->decay)); { fp16p16_t tmp = ftofp16p16(0.1); am_step = mulfp16p16((-line->volume), tmp); tmp = itofp16p16(elimit); am_step = divfp16p16(am_step, tmp); } // am_step = divfp16p16(mulfp16p16((-line->volume), ftofp16p16(0.1)), itofp16p16(elimit)); break; case 2: // Sustain elimit = 0; am_step = 0; break; case 3: // this is actually never reached // because of the new "hold" // stuff in Hold Comment A break; case 4: // Release elimit = fp16p16toi(mulfp16p16(itofp16p16(4000), info->release)); { fp16p16_t tmp = ftofp16p16(0.9); am_step = mulfp16p16((-amplitude), tmp); tmp = itofp16p16(elimit); am_step = divfp16p16(am_step, tmp); } break; case 5: // Silence elimit = 4000; am_step = itofp16p16(0); amplitude = itofp16p16(0); break; } } index = (index + 1) % (1000 * period); } info->index = index; info->wa_step = wa_step; info->amplitude = amplitude; info->am_step = am_step; info->elimit = elimit; info->envelope = envelope; info->period = period; }