description Jérôme Burlando BSD beatslicer.axh zero crossing check activate uint32_t zerocrosspoint = 0; // zero crossing index in wave table int32_t twoframe[2 * FRAME_SIZE]; // Buffer used for temporary continuous recording uint8_t tfi = 0; // Two frame buffer index uint8_t curchunk = 0; // Current chunk number uint8_t detect = 0; // Detection status : 1 => store slice in slicebuffer int32_t peakenvelope = 0; // Current envelope value expressed in decibel int32_t diff = 0; // For attackstep calibration output int32_t attack = 0; // [user] Decibel absolute threshold for attack test int32_t decay = 0; // [user] Threshold for attack detection on difference of previous peakenvelope and current peakenvelope int32_t silence = 0; // [user] Decibel threshold for silence test uint32_t radius = 130685889; // (uint32_t) (exp(-1.33333333f / 1000) * (1<<27)); uint8_t trig = 0; // For display a value each second : if(!calib_cpt) LogTextMessage("val : %d", val); /* Take a frac32 value and return the equivalent value in logarithmic scale * From axoloti "log" object. */ int32_t logscale(int32_t in) { Float_t f; f.f = in; int32_t r1 = ((f.parts.exponent&0x7F)-18) << 24; int32_t r3 = logt[f.parts.mantissa>>15]<<10; return r1 + r3; } /* Convert rms power value to decibel unit */ int32_t rmstodb(int32_t rms) { int32_t y = logscale(rms); // 16 + 8 * log2(x) return ___SMMUL(y - 16, LOG2_10); // decibel = 10 * log10(power / power_ref) // <=> 10 * log2(x) / log2(10) with power_ref == 1 (1 << 27) } /* Apply an half Hanning window on the begin of the recorded sample (2 frames) * Hanning is full range (input in range 0..MAX_INT). * Start on the begin of the hanning window and finish on the middle the hanning window. */ void insert_twoframe(void) { int32_t s = 0; uint32_t phase = 0; int8_t tfitmp = tfi; int32_t r; int8_t i; for(i = 0; i < FRAME_SIZE; i++){ HANNING2TINTERP(phase, r) /* "<< 5" to complete ___SMMUL operation (fixed point choice contraint) * ">> 4" => just a copy of the hanning window axoloti object. Why not >> 5 ? I don't understand. */ s = ___SMMUL(twoframe[tfitmp++], r >> 4) << 5; attr_slicesbuffer.array[si++] = __SSAT(s,28)>>attr_slicesbuffer.GAIN; tfitmp %= FRAME_SIZE * 2; phase += HANINC; } for(i = 0; i < FRAME_SIZE; i++){ s = twoframe[tfitmp++]; attr_slicesbuffer.array[si++] = __SSAT(s,28)>>attr_slicesbuffer.GAIN; tfitmp %= FRAME_SIZE * 2; } } /* Apply an half Hanning window on the end of the recorded sample (2 frames) * Hanning is full range (input in range 0..MAX_INT). * Start on the middle of the hanning window and finish on the end the hanning window. */ void fadeout(uint32_t cuepoint) { /* MAX_INT / 2 => hanning window is full range (input in range 0..MAX_INT). * Start on the middle of the hanning window. */ uint32_t phase = HANMID; int32_t r; int32_t s; for(int i = cuepoint - (2 * FRAME_SIZE); i < cuepoint; i++){ HANNING2TINTERP(phase, r) s = ___SMMUL(attr_slicesbuffer.array[i], r >> 4) << 5; // see "insert_twoframe" attr_slicesbuffer.array[i] = __SSAT(s,28)>>attr_slicesbuffer.GAIN; phase += (HANINC / 2); // HANINC is a FRAMESIZE increment. Fadeout apply a fadeout on 2 frames. } /* Store cuepoint */ if(sii < attr_slicesindex.LENGTH){ attr_slicesindex.array[0] = sii; attr_slicesindex.array[sii++] = cuepoint; } } void detection() { int32_t peakenvelope_tmp = peakenvelope; rms >>= 2; // rms = rms << 5 (to complete last ___SMMLA operation) and >> 7 (/ 128) for the mean value int32_t decibel = rms > 1 ? rmstodb(rms) : 0; // rmstodb produce bad value with a very little value of rms diff = decibel - peakenvelope_tmp; // New slice detection if((decibel > attack) && (diff > decay) && !(timer > 0)) { trig = 1; if(!(detect)) { insert_twoframe(); detect = 1; } else { fadeout(zerocrosspoint); } timer = INITTIMER; // To avoid closed detections } peakenvelope_tmp = ___SMMUL(radius, peakenvelope_tmp) << 5; // << 5 (to complete ___SMMUL operation if(decibel > peakenvelope_tmp) peakenvelope_tmp = decibel; // Silence detection if(detect && !(timer > 0) && (peakenvelope_tmp < silence)) { detect = 0; fadeout(si); } peakenvelope = peakenvelope_tmp; }]]> 0 && !preset) { preset = 1; si = 0; sii = 1; attr_slicesindex.array[0] = 0; } else if(!(inlet_reset>0)) { preset = 0; } if(timer > 0) timer--; for(int i = 0; i < BUFSIZE; i++){ s = inlet_in[i]; if(detect){ if(crosscheck && (prev_s * s < 0)){ zerocrosspoint_tmp = si; crosscheck = 0; } attr_slicesbuffer.array[si++] = __SSAT(s,28)>>attr_slicesbuffer.GAIN; } else { twoframe[tfi++] = s; } rms = __USAT(___SMMLA(s, s, rms), 27); // rms += s * s (must apply "<< 5" in order to exactly have the sum of square) prev_s = s; } tfi %= 2 * FRAME_SIZE; if(curchunk == NB_CHUNK_FRAME - 1){ crosscheck = 1; detection(); // Attack and decay to zero detection zerocrosspoint = zerocrosspoint_tmp; rms = 0; } curchunk++; curchunk %= NB_CHUNK_FRAME; /************************/ /* Displays and outputs */ /************************/ disp_detection = detect; outlet_detection = trig; outlet_rms = peakenvelope; outlet_diff = diff;]]> play audio from table (non-transposed), starting from position Johannes Taelman BSD table.axh 0) && !pstart) { pstart = 1; if(inlet_nslice < attr_slicesindex.array[0]) { if(inlet_nslice == 0) { pos = 0; end = attr_slicesindex.array[1]; } else { pos = attr_slicesindex.array[inlet_nslice]; end = attr_slicesindex.array[inlet_nslice+1]; } } } else if (!(inlet_start>0)) { pstart = 0; }]]> polyphonic 1 true 8 32 8 8 382 74 820 584 no 10 8 32 8 8 49 -4 1317 772