int mathClipInt(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b, *c; double lo, hi; int err; a = g->sp - 2; b = g->sp - 1; c = g->sp; if (IsSym(b)) { *a = *b; } else if (IsSym(c)) { *a = *c; } else if (IsInt(b) && IsInt(c)) { SetRaw(a, sc_clip(slotRawInt(a), slotRawInt(b), slotRawInt(c))); } else { err = slotDoubleVal(b, &lo); if (err) return err; err = slotDoubleVal(c, &hi); if (err) return err; SetFloat(a, sc_clip((double)slotRawInt(a), lo, hi)); } return errNone; }
SCErr meth_b_fill(World *inWorld, int inSize, char *inData, ReplyAddress* /*inReply*/) { sc_msg_iter msg(inSize, inData); int bufindex = msg.geti(); SndBuf* buf = World_GetBuf(inWorld, bufindex); if (!buf) return kSCErr_Failed; float *data = buf->data; int numSamples = buf->samples; while (msg.remain() >= 12) { int32 start = msg.geti(); int32 n = msg.geti(); float32 value = msg.getf(); int32 end = start+n-1; if (end < 0 || start >= numSamples) continue; start = sc_clip(start, 0, numSamples-1); end = sc_clip(end, 0, numSamples-1); for (int i=start; i<=end; ++i) data[i] = value; } return kSCErr_None; }
SCErr meth_c_fill(World *inWorld, int inSize, char *inData, ReplyAddress* /*inReply*/) { sc_msg_iter msg(inSize, inData); float *data = inWorld->mControlBus; int32 *touched = inWorld->mControlBusTouched; int32 bufCounter = inWorld->mBufCounter; int maxIndex = inWorld->mNumControlBusChannels; while (msg.remain() >= 12) { int32 start = msg.geti(); int32 n = msg.geti(); float32 value = msg.getf(); int32 end = start+n-1; if (end < 0 || start >= maxIndex) continue; start = sc_clip(start, 0, maxIndex-1); end = sc_clip(end, 0, maxIndex-1); for (int i=start; i<=end; ++i) { data[i] = value; touched[i] = bufCounter; } } return kSCErr_None; }
int initMIDI(int numIn, int numOut) { midiCleanUp(); numIn = sc_clip(numIn, 1, kMaxMidiPorts); numOut = sc_clip(numOut, 1, kMaxMidiPorts); int enc = kCFStringEncodingMacRoman; CFAllocatorRef alloc = CFAllocatorGetDefault(); CFStringRef clientName = CFStringCreateWithCString(alloc, "SuperCollider", enc); OSStatus err = MIDIClientCreate(clientName, midiNotifyProc, nil, &gMIDIClient); if (err) { post("Could not create MIDI client. error %d\n", err); return errFailed; } CFRelease(clientName); for (int i=0; i<numIn; ++i) { char str[32]; sprintf(str, "in%d\n", i); CFStringRef inputPortName = CFStringCreateWithCString(alloc, str, enc); err = MIDIInputPortCreate(gMIDIClient, inputPortName, midiReadProc, &i, gMIDIInPort+i); if (err) { gNumMIDIInPorts = i; post("Could not create MIDI port %s. error %d\n", str, err); return errFailed; } CFRelease(inputPortName); } /*int n = MIDIGetNumberOfSources(); printf("%d sources\n", n); for (i = 0; i < n; ++i) { MIDIEndpointRef src = MIDIGetSource(i); MIDIPortConnectSource(inPort, src, NULL); }*/ gNumMIDIInPorts = numIn; for (int i=0; i<numOut; ++i) { char str[32]; sprintf(str, "out%d\n", i); CFStringRef outputPortName = CFStringCreateWithCString(alloc, str, enc); err = MIDIOutputPortCreate(gMIDIClient, outputPortName, gMIDIOutPort+i); if (err) { gNumMIDIOutPorts = i; post("Could not create MIDI out port. error %d\n", err); return errFailed; } CFRelease(outputPortName); } gNumMIDIOutPorts = numOut; return errNone; }
int prSpeakText(struct VMGlobals *g, int numArgsPushed){ OSErr theErr = noErr; PyrSlot *obj = g->sp-2; PyrSlot *a = g->sp-1; PyrSlot *str = g->sp; int chan; slotIntVal(a, &chan); chan = sc_clip(chan, 0, kMaxSpeechChannels); if(speechStrings[chan] != NULL) { post("voice %i already speaking\n", chan); return errNone; } else { // speechStrings[chan] = (char*)pyr_pool_compile->Alloc((a->uo->size + 1)* sizeof(char)); speechStrings[chan] = (char*) malloc((str->uo->size + 1)* sizeof(char)); MEMFAIL(speechStrings[chan]); slotStrVal(str, speechStrings[chan], str->uo->size+1); //if(!fCurSpeechChannel) theErr = NewSpeechChannel( NULL, &fCurSpeechChannel ); theErr = SpeakText( fCurSpeechChannel[chan], speechStrings[chan], strlen(speechStrings[chan])); //should be freed only after the text was spoken! // todo move this bit to the callback! // pyr_pool_compile->Free(theTextToSpeak); } return errNone; }
int prHIDBuildElementList(VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 2; //class PyrSlot *b = g->sp - 1; //locID device PyrSlot *c = g->sp; //array int locID; int err = slotIntVal(b, &locID); if (err) return err; //look for the right device: pRecDevice pCurrentHIDDevice = HIDGetFirstDevice (); while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID)) pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice); if(!pCurrentHIDDevice) return errFailed; pRecElement devElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeAll ); UInt32 numElements = HIDCountDeviceElements (pCurrentHIDDevice, kHIDElementTypeAll ); // PyrObject* devAllElementsArray = newPyrArray(g->gc, numElements * sizeof(PyrObject), 0 , true); PyrObject *devAllElementsArray = c->uo; // post("numElements: %d\n", numElements); numElements = sc_clip(numElements, 0, devAllElementsArray->size); for(uint i=0; i<numElements; i++){ if(devElement){ char cstrElementName [256]; PyrObject* devElementArray = newPyrArray(g->gc, 8 * sizeof(PyrObject), 0 , true); // type name (1) HIDGetTypeName((IOHIDElementType) devElement->type, cstrElementName); PyrString *devstring = newPyrString(g->gc, cstrElementName, 0, true); SetObject(devElementArray->slots+devElementArray->size++, devstring); //g->gc->GCWrite(devElementArray, (PyrObject*) devstring); //usage (2) HIDGetUsageName (devElement->usagePage, devElement->usage, cstrElementName); PyrString *usestring = newPyrString(g->gc, cstrElementName, 0, true); SetObject(devElementArray->slots+devElementArray->size++, usestring); //g->gc->GCWrite(devElementArray, (PyrObject*) usestring); //cookie (3) SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->cookie); // min (4) SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->min); // max (5) SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->max); // IO type as int: (6) SetInt(devElementArray->slots+devElementArray->size++, (int) devElement->type); // Usage page as int: (7) SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->usagePage); // Usage type as int: (8) SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->usage); SetObject(devAllElementsArray->slots+i, devElementArray); //g->gc->GCWrite(devAllElementsArray, (PyrObject*) devElementArray); } devElement = HIDGetNextDeviceElement (devElement, kHIDElementTypeAll); } SetObject(a, devAllElementsArray); return errNone; }
long nextPrime(int n) { // binary search of primes table int i, p, lo = 0, hi = NUMPRIMES-1; while (hi>=lo) { i = (lo + hi) >> 1; p = nthPrime(i); if (n==p) return i; if (n<p) hi = i - 1; else lo = i + 1; } return sc_clip(lo, 0, NUMPRIMES-1); }
void FFT_Ctor(FFT *unit) { int winType = sc_clip((int)ZIN0(3), -1, 1); // wintype may be used by the base ctor unit->m_wintype = winType; if(!FFTBase_Ctor(unit, 5)){ SETCALC(FFT_ClearUnitOutputs); // These zeroes are to prevent the dtor freeing things that don't exist: unit->m_inbuf = 0; unit->m_scfft = 0; return; } int audiosize = unit->m_audiosize * sizeof(float); int hopsize = (int)(sc_max(sc_min(ZIN0(2), 1.f), 0.f) * unit->m_audiosize); if (hopsize < unit->mWorld->mFullRate.mBufLength) { Print("FFT_Ctor: hopsize smaller than SC's block size (%i) - automatically corrected.\n", hopsize, unit->mWorld->mFullRate.mBufLength); hopsize = unit->mWorld->mFullRate.mBufLength; } else if (((int)(hopsize / unit->mWorld->mFullRate.mBufLength)) * unit->mWorld->mFullRate.mBufLength != hopsize) { Print("FFT_Ctor: hopsize (%i) not an exact multiple of SC's block size (%i) - automatically corrected.\n", hopsize, unit->mWorld->mFullRate.mBufLength); hopsize = ((int)(hopsize / unit->mWorld->mFullRate.mBufLength)) * unit->mWorld->mFullRate.mBufLength; } unit->m_hopsize = hopsize; unit->m_shuntsize = unit->m_audiosize - hopsize; unit->m_inbuf = (float*)RTAlloc(unit->mWorld, audiosize); SCWorld_Allocator alloc(ft, unit->mWorld); unit->m_scfft = scfft_create(unit->m_fullbufsize, unit->m_audiosize, (SCFFT_WindowFunction)unit->m_wintype, unit->m_inbuf, unit->m_fftsndbuf->data, kForward, alloc); if (!unit->m_scfft) { SETCALC(*ClearUnitOutputs); return; } memset(unit->m_inbuf, 0, audiosize); //Print("FFT_Ctor: hopsize %i, shuntsize %i, bufsize %i, wintype %i, \n", // unit->m_hopsize, unit->m_shuntsize, unit->m_bufsize, unit->m_wintype); if (INRATE(1) == calc_FullRate) { unit->m_numSamples = unit->mWorld->mFullRate.mBufLength; } else { unit->m_numSamples = 1; } SETCALC(FFT_next); }
static void SC_LinuxSetRealtimePriority(pthread_t thread, int priority) { int policy; struct sched_param param; pthread_getschedparam(thread, &policy, ¶m); policy = SCHED_FIFO; const int minprio = sched_get_priority_min(policy); const int maxprio = sched_get_priority_max(policy); param.sched_priority = sc_clip(priority, minprio, maxprio); int err = pthread_setschedparam(thread, policy, ¶m); if (err != 0) { post("Couldn't set realtime scheduling priority %d: %s\n", param.sched_priority, strerror(err)); } }
void set_real_time_priority(pthread_t thread) { int policy; struct sched_param param; pthread_getschedparam (thread, &policy, ¶m); #ifdef __linux__ policy = SCHED_FIFO; const char* env = getenv("SC_SCHED_PRIO"); // jack uses a priority of 10 in realtime mode, so this is a good default const int defprio = 5; const int minprio = sched_get_priority_min(policy); const int maxprio = sched_get_priority_max(policy); const int prio = env ? atoi(env) : defprio; param.sched_priority = sc_clip(prio, minprio, maxprio); #else policy = SCHED_RR; // round-robin, AKA real-time scheduling param.sched_priority = 63; // you'll have to play with this to see what it does #endif pthread_setschedparam (thread, policy, ¶m); }
void RedPhasor_next_kk(RedPhasor *unit, int inNumSamples) { float *out= ZOUT(0); float in= ZIN0(0); float rate= sc_max(0, ZIN0(1)); double start= ZIN0(2); double end= ZIN0(3); float loop= ZIN0(4); float previn= unit->m_previn; double level= unit->mLevel; if((previn<=0.f)&&(in>0.f)) { level= start; } if(loop<=0.f) { //kk off if(end<start) { LOOP(inNumSamples, ZXP(out)= level; level-= rate; level= sc_clip(level, end, start); ); } else {
void IFFT_Ctor(IFFT* unit){ int winType = sc_clip((int)ZIN0(1), -1, 1); // wintype may be used by the base ctor unit->m_wintype = winType; if(!FFTBase_Ctor(unit, 2)){ SETCALC(*ClearUnitOutputs); // These zeroes are to prevent the dtor freeing things that don't exist: unit->m_olabuf = 0; return; } // This will hold the transformed and progressively overlap-added data ready for outputting. unit->m_olabuf = (float*)RTAlloc(unit->mWorld, unit->m_audiosize * sizeof(float)); memset(unit->m_olabuf, 0, unit->m_audiosize * sizeof(float)); SCWorld_Allocator alloc(ft, unit->mWorld); unit->m_scfft = scfft_create(unit->m_fullbufsize, unit->m_audiosize, (SCFFT_WindowFunction)unit->m_wintype, unit->m_fftsndbuf->data, unit->m_fftsndbuf->data, kBackward, alloc); if (!unit->m_scfft) { SETCALC(*ClearUnitOutputs); unit->m_olabuf = 0; return; } // "pos" will be reset to zero when each frame comes in. Until then, the following ensures silent output at first: unit->m_pos = 0; //unit->m_audiosize; if (unit->mCalcRate == calc_FullRate) { unit->m_numSamples = unit->mWorld->mFullRate.mBufLength; } else { unit->m_numSamples = 1; } SETCALC(IFFT_next); ClearUnitOutputs(unit, 1); }
int prString_FindRegexp(struct VMGlobals *g, int numArgsPushed) { int err; PyrSlot *a = g->sp - 2; // source string PyrSlot *b = g->sp - 1; // pattern PyrSlot *c = g->sp; // offset if (!isKindOfSlot(b, class_string) || (NotInt(c))) return errWrongType; // post("prString_FindRegexp\n"); int maxfind = MAXREGEXFIND; int offset = slotRawInt(c); int stringsize = slotRawObject(a)->size + 1; int patternsize = slotRawObject(b)->size + 1; char *string = (char*)malloc(slotRawObject(a)->size + 1); err = slotStrVal(a, string, slotRawObject(a)->size + 1); if (err){ free(string); return err; } char *pattern = (char*)malloc(slotRawObject(b)->size + 1); err = slotStrVal(b, pattern, slotRawObject(b)->size + 1); if (err) return err; UParseError uerr; UErrorCode status = (UErrorCode)0; UChar *regexStr; UChar *ustring; regexStr = (UChar*)malloc((patternsize)*sizeof(UChar)); u_charsToUChars (pattern, regexStr, patternsize); ustring = (UChar*)malloc((stringsize)*sizeof(UChar)); u_charsToUChars (string+offset, ustring, stringsize-offset); unsigned flags = UREGEX_MULTILINE; int groupNumber = 0; SCRegExRegion * what; int indx = 0; int size = 0; URegularExpression *expression = uregex_open(regexStr, -1, flags, &uerr, &status); if(U_FAILURE(status)) goto nilout; if(!U_FAILURE(status)) { uregex_setText(expression, ustring, -1, &status); what = (SCRegExRegion*)malloc((maxfind)*sizeof(SCRegExRegion)); for(int i=0; i< maxfind; i++) { SCRegExRegion range; range.matched = false; what[i] = range; } int32_t groups = uregex_groupCount(expression, &status) + 1; if(U_FAILURE(status)) goto nilout; // post("groups: %i\n", groups); while (uregex_findNext(expression, &status) && size<maxfind) { if(U_FAILURE(status)) return errNone; for(int i=0; i< groups; ++i){ what[size].group = i; what[size].start = sc_clip(uregex_start(expression, i, &status), 0, stringsize) ; if(U_FAILURE(status)) goto nilout; what[size].end = sc_clip(uregex_end(expression, i, &status), 0, stringsize); what[size].matched = true; // post("index:%i, size:%i, start %i, end %i\n", i, size, what[i].start, what[i].end); size = indx++ + 1; if(U_FAILURE(status)) goto nilout; } } PyrObject *result_array = newPyrArray(g->gc, size, 0, true); result_array->size = 0; if (size>0) //(matched) { for (int i = 0; i < size; i++) { if (what[0].matched == false) { result_array->size++; SetNil(result_array->slots+i); } else { result_array->size++; int match_start = what[i].start; int match_length = what[i].end - what[i].start; // post("for i:%i, start %i, end %i\n", i, what[i].start, what[i].end); // char *match = (char*)malloc(match_length); char match[match_length]; strncpy(match, string + offset + match_start, match_length); match[match_length] = 0; PyrObject *array = newPyrArray(g->gc, 2, 0, true); array->size = 2; SetInt(array->slots, match_start + offset); PyrObject *matched_string = (PyrObject*)newPyrString(g->gc, match, 0, true); SetObject(array->slots+1, matched_string); g->gc->GCWrite(matched_string, array->slots + 1); SetObject(result_array->slots + i, array); g->gc->GCWrite(array, result_array->slots + i); } } } else { SetNil(a); } free(what); free(pattern); free(regexStr); free(ustring); free(string); SetObject(a, result_array); g->gc->GCWrite(result_array,a); //uregex_close(expression); return errNone; } nilout: free(string); free(what); free(pattern); free(regexStr); free(ustring); SetNil(a); return errNone; }
void SVF_next(SVF *unit, int inNumSamples) { float *out = OUT(0); float *in = IN(0); float cutoff = IN0(1); float resonance = IN0(2); float lowlevel = IN0(3); float bandlevel = IN0(4); float highlevel = IN0(5); float notchlevel = IN0(6); float peaklevel = IN0(7); // float drive = IN0(8); cutoff = sc_clip(cutoff, 20.f, SAMPLERATE); resonance = sc_clip(resonance, 0.f, 1.f); lowlevel = sc_clip(lowlevel, 0.f, 1.f); bandlevel = sc_clip(bandlevel, 0.f, 1.f); highlevel = sc_clip(highlevel, 0.f, 1.f); notchlevel = sc_clip(notchlevel, 0.f, 1.f); peaklevel = sc_clip(peaklevel, 0.f, 1.f); // drive = sc_clip(drive, 0.f, 1.f) * 0.1; float m_freq, m_damp; if (cutoff != unit->m_cutoff || resonance != unit->m_resonance) { unit->m_cutoff = cutoff; unit->m_resonance = resonance; unit->m_freq = m_freq = (float)(2.f * sin(pi * sc_min(0.25, cutoff / (SAMPLERATE * 2.f)))); unit->m_damp = m_damp = sc_min(2.0 * (1.0 - pow(resonance, 0.25f)), (double)sc_min(2.f, 2.f / m_freq - m_freq * 0.5f)); } else { m_freq = unit->m_freq; m_damp = unit->m_damp; } float input; float low; float band; float high; float notch; float outPeak; float m_notch = unit->m_notch; float m_low = unit->m_low; float m_high = unit->m_high; float m_band = unit->m_band; for (long i = 0; i < inNumSamples; ++i) { input = in[i]; // First iteration m_notch = input - m_damp * m_band; m_low = m_low + m_freq * m_band; m_high = m_notch - m_low; m_band = m_freq * m_high + m_band; low = 0.5f * m_low; band = 0.5f * m_band; high = 0.5f * m_high; notch = 0.5f * m_notch; outPeak = 0.5f * (m_low - m_high); // Double sampled... m_notch = input - m_damp * m_band; m_low = m_low + m_freq * m_band; m_high = m_notch - m_low; m_band = m_freq * m_high + m_band; low += 0.5f * m_low; band += 0.5f * m_band; high += 0.5f * m_high; notch += 0.5f * m_notch; outPeak += 0.5f * (m_low - m_high); out[i] = (low * lowlevel) + (band * bandlevel) + (high * highlevel) + (notch * notchlevel) + (outPeak * peaklevel); } unit->m_notch = m_notch; unit->m_low = m_low; unit->m_high = m_high; unit->m_band = m_band; }
void DWGPlucked2_next(DWGPlucked2 *unit, int inNumSamples) { float *out = OUT(0); float freq = ZIN0(0); float amp = ZIN0(1); float trig = ZIN0(2); float pos = ZIN0(3); float c1 = ZIN0(4); float c3 = std::max(ZIN0(5),(float)1e-9); float *in = IN(6); float mistune = ZIN0(8); float mp = sc_clip(ZIN0(9),0,1); float gc = ZIN0(10); unit->Loss.setcoeffs(freq,c1,c3); float lossdelay = unit->Loss.groupdelay(freq,SAMPLERATE); float deltot = SAMPLERATE/freq; float del1 = (deltot - lossdelay )*0.5 - 1; float freq2 = freq * mistune; unit->Loss2.setcoeffs(freq2,c1,c3); lossdelay = unit->Loss2.groupdelay(freq2,SAMPLERATE); deltot = SAMPLERATE/freq2; float del2 = (deltot - lossdelay )*0.5 - 1; float PMAS,PMAS2; float PMENOS,OUT1,OUT2; for (int i=0; i < inNumSamples; ++i) { unit->DWGF[0].add(in[i]*mp,pos*del1); unit->DWGF[1].add(in[i]*mp,del1*(1-pos)); PMAS = unit->DWGF[0].delay(del1); PMAS2 = unit->Loss.filter(PMAS); PMENOS = unit->DWGF[1].delay(del1); unit->DWGF[1].push(-PMAS2); unit->DWGF[0].push(-PMENOS); OUT1 = PMAS + PMAS2; unit->DWGF2[0].add(in[i]*(1-mp)+OUT1*gc,pos*del2); unit->DWGF2[1].add(in[i]*(1-mp)+OUT1*gc,del2*(1-pos)); PMAS = unit->DWGF2[0].delay(del2); PMAS2 = unit->Loss2.filter(PMAS); PMENOS = unit->DWGF2[1].delay(del2); unit->DWGF2[1].push(-PMAS2);//*0.9999); unit->DWGF2[0].push(-PMENOS); OUT2 = PMAS + PMAS2; out[i] = OUT1 + OUT2; } unit->Release(trig,out,inNumSamples); }
void set_q(double q_) { q = sc_clip(q_, 0, 1); k = 20 * q; A = 1 + 0.5*k; // resonance gain compensation }