📄 resample.c
字号:
INTERPVARS; Voice *vp=&voice[v]; resample_t *dest=resample_buffer; sample_t *src=vp->sample->data; int32 le=vp->sample->data_length, ofs=vp->sample_offset, incr=vp->sample_increment, count=*countptr; int cc=vp->vibrato_control_counter; /* This has never been tested */ if (incr<0) incr = -incr; /* In case we're coming out of a bidir loop */ while (count--) { if (!cc--) { cc=vp->vibrato_control_ratio; incr=update_vibrato(vp, 0); } RESAMPLATION; ofs += incr; if (ofs >= le) { FINALINTERP; vp->status=VOICE_FREE; ctl->note(v); *countptr-=count+1; break; } } vp->vibrato_control_counter=cc; vp->sample_increment=incr; vp->sample_offset=ofs; /* Update offset */ return resample_buffer;}static resample_t *rs_vib_loop(Voice *vp, int32 count){ /* Play sample until end-of-loop, skip back and continue. */ INTERPVARS; int32 ofs=vp->sample_offset, incr=vp->sample_increment, le=vp->sample->loop_end, ll=le - vp->sample->loop_start; resample_t *dest=resample_buffer; sample_t *src=vp->sample->data; int cc=vp->vibrato_control_counter;#ifdef PRECALC_LOOPS int32 i; int vibflag=0; while (count) { /* Hopefully the loop is longer than an increment */ if(ofs >= le) ofs -= ll; /* Precalc how many times to go through the loop, taking the vibrato control ratio into account this time. */ i = (le - ofs) / incr + 1; if(i > count) i = count; if(i > cc) { i = cc; vibflag = 1; } else cc -= i; count -= i; while(i--) { RESAMPLATION; ofs += incr; } if(vibflag) { cc = vp->vibrato_control_ratio; incr = update_vibrato(vp, 0); vibflag = 0; } }#else /* PRECALC_LOOPS */ while (count--) { if (!cc--) { cc=vp->vibrato_control_ratio; incr=update_vibrato(vp, 0); } RESAMPLATION; ofs += incr; if (ofs>=le) ofs -= ll; /* Hopefully the loop is longer than an increment. */ }#endif /* PRECALC_LOOPS */ vp->vibrato_control_counter=cc; vp->sample_increment=incr; vp->sample_offset=ofs; /* Update offset */ return resample_buffer;}static resample_t *rs_vib_bidir(Voice *vp, int32 count){ INTERPVARS; int32 ofs=vp->sample_offset, incr=vp->sample_increment, le=vp->sample->loop_end, ls=vp->sample->loop_start; resample_t *dest=resample_buffer; sample_t *src=vp->sample->data; int cc=vp->vibrato_control_counter;#ifdef PRECALC_LOOPS int32 le2=le<<1, ls2=ls<<1, i; int vibflag = 0; /* Play normally until inside the loop region */ while (count && (ofs <= ls)) { i = (ls - ofs) / incr + 1; if (i > count) i = count; if (i > cc) { i = cc; vibflag = 1; } else cc -= i; count -= i; while (i--) { RESAMPLATION; ofs += incr; } if (vibflag) { cc = vp->vibrato_control_ratio; incr = update_vibrato(vp, 0); vibflag = 0; } } /* Then do the bidirectional looping */ while (count) { /* Precalc how many times we should go through the loop */ i = ((incr > 0 ? le : ls) - ofs) / incr + 1; if(i > count) i = count; if(i > cc) { i = cc; vibflag = 1; } else cc -= i; count -= i; while (i--) { RESAMPLATION; ofs += incr; } if (vibflag) { cc = vp->vibrato_control_ratio; incr = update_vibrato(vp, (incr < 0)); vibflag = 0; } if (ofs >= le) { /* fold the overshoot back in */ ofs = le2 - ofs; incr *= -1; } else if (ofs <= ls) { ofs = ls2 - ofs; incr *= -1; } }#else /* PRECALC_LOOPS */ /* Play normally until inside the loop region */ if (ofs < ls) { while (count--) { if (!cc--) { cc=vp->vibrato_control_ratio; incr=update_vibrato(vp, 0); } RESAMPLATION; ofs += incr; if (ofs>=ls) break; } } /* Then do the bidirectional looping */ if (count>0) while (count--) { if (!cc--) { cc=vp->vibrato_control_ratio; incr=update_vibrato(vp, (incr < 0)); } RESAMPLATION; ofs += incr; if (ofs>=le) { /* fold the overshoot back in */ ofs = le - (ofs - le); incr = -incr; } else if (ofs <= ls) { ofs = ls + (ls - ofs); incr = -incr; } }#endif /* PRECALC_LOOPS */ vp->vibrato_control_counter=cc; vp->sample_increment=incr; vp->sample_offset=ofs; /* Update offset */ return resample_buffer;}resample_t *resample_voice(int v, int32 *countptr){ int32 ofs; uint8 modes; Voice *vp=&voice[v]; if (!(vp->sample->sample_rate)) { /* Pre-resampled data -- just update the offset and check if we're out of data. */ ofs=vp->sample_offset >> FRACTION_BITS; /* Kind of silly to use FRACTION_BITS here... */ if (*countptr >= (vp->sample->data_length>>FRACTION_BITS) - ofs) { /* Note finished. Free the voice. */ vp->status = VOICE_FREE; ctl->note(v); /* Let the caller know how much data we had left */ *countptr = (vp->sample->data_length>>FRACTION_BITS) - ofs; } else vp->sample_offset += *countptr << FRACTION_BITS; return (resample_t *)vp->sample->data+ofs; } /* Need to resample. Use the proper function. */ modes=vp->sample->modes; if (vp->vibrato_control_ratio) { if ((modes & MODES_LOOPING) && ((modes & MODES_ENVELOPE) || (vp->status==VOICE_ON || vp->status==VOICE_SUSTAINED))) { if (modes & MODES_PINGPONG) return rs_vib_bidir(vp, *countptr); else return rs_vib_loop(vp, *countptr); } else return rs_vib_plain(v, countptr); } else { if ((modes & MODES_LOOPING) && ((modes & MODES_ENVELOPE) || (vp->status==VOICE_ON || vp->status==VOICE_SUSTAINED))) { if (modes & MODES_PINGPONG) return rs_bidir(vp, *countptr); else return rs_loop(vp, *countptr); } else return rs_plain(v, countptr); }}void pre_resample(Sample * sp){ double a, xdiff; int32 incr, ofs, newlen, count; int16 *src = (int16 *) sp->data; resample_t *newdata, *dest; int16 v1, v2, v3, v4, *vptr; static const char note_name[12][3] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; ctl->cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)", sp->note_to_use, note_name[sp->note_to_use % 12], (sp->note_to_use & 0x7F) / 12); a = ((double) (sp->sample_rate) * freq_table[(int) (sp->note_to_use)]) / ((double) (sp->root_freq) * play_mode->rate); if (a <= 0) return; newlen = (int32)(sp->data_length / a); if (newlen < 0 || (newlen >> FRACTION_BITS) > MAX_SAMPLE_SIZE) return; dest = newdata = safe_malloc(newlen >> (FRACTION_BITS - 1)); count = (newlen >> FRACTION_BITS) - 1; ofs = incr = (sp->data_length - (1 << FRACTION_BITS)) / count; if (--count) *dest++ = src[0]; /* Since we're pre-processing and this doesn't have to be done in real-time, we go ahead and do the full sliding cubic interpolation. */ while (--count) { vptr = src + (ofs >> FRACTION_BITS); v1 = *(vptr - 1); v2 = *vptr; v3 = *(vptr + 1); v4 = *(vptr + 2); xdiff = FSCALENEG(ofs & FRACTION_MASK, FRACTION_BITS); *dest++ = (int16)(v2 + (xdiff / 6.0) * (-2 * v1 - 3 * v2 + 6 * v3 - v4 + xdiff * (3 * (v1 - 2 * v2 + v3) + xdiff * (-v1 + 3 * (v2 - v3) + v4)))); ofs += incr; } if (ofs & FRACTION_MASK) { v1 = src[ofs >> FRACTION_BITS]; v2 = src[(ofs >> FRACTION_BITS) + 1]; *dest++ = (resample_t)(v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS)); } else *dest++ = src[ofs >> FRACTION_BITS]; sp->data_length = newlen; sp->loop_start = (int32)(sp->loop_start / a); sp->loop_end = (int32)(sp->loop_end / a); free(sp->data); sp->data = (sample_t *) newdata; sp->sample_rate = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -