History

added tSimplePoly

spiricom committed 6 years ago

Commit a7eedc61 parent fe679cd5 files · +323 −0Browse files

Unified · Split

5 files
  1. .DS_Store +0 −0
  2. LEAF/.DS_Store +0 −0
  3. LEAF/Inc/leaf-midi.h +128 −0
  4. LEAF/Src/leaf-effects.c +2 −2
  5. LEAF/Src/leaf-midi.c +195 −0
.DS_Store+0−0

Binary file not shown.

LEAF/.DS_Store+0−0

Binary file not shown.

LEAF/Inc/leaf-midi.h+128−0
@@ -362,6 +362,134 @@ extern "C" { · 361 unmodified lines
362362 /*! @} */
363363
364364 //==============================================================================
365+
366+
367+ // simplified version of poly for more efficiency when we don't need ramps and pitch glide
368+ /*!
369+ * @defgroup tpoly tPoly
370+ * @ingroup midi
371+ * @brief An object for polyphonic handling.
372+ * @{
373+ */
374+
375+ /* tPoly */
376+ typedef struct _tSimplePoly
377+ {
378+ tStack stack;
379+
380+ int numVoices;
381+ int maxNumVoices;
382+ int** voices;
383+
384+ int notes[128][2];
385+ } _tSimplePoly;
386+
387+ typedef _tSimplePoly* tSimplePoly;
388+
389+ //! Initialize a tPoly to the default LEAF mempool.
390+ /*!
391+ @param poly A pointer to the tPoly to be initialized.
392+ @param maxNumVoices The maximum number of voices this tPoly can handle at once.
393+ */
394+ void tSimplePoly_init (tSimplePoly* const poly, int maxNumVoices);
395+
396+
397+ //! Free a tPoly from the default LEAF mempool.
398+ /*!
399+ @param poly A pointer to the tPoly to be freed.
400+ */
401+ void tSimplePoly_free (tSimplePoly* const poly);
402+
403+
404+ //! Initialize a tPoly to a specified mempool.
405+ /*!
406+ @param poly A pointer to the tPoly to be initialized.
407+ @param pool A pointer to the tMempool to which the tPoly should be initialized.
408+ */
409+ void tSimplePoly_initToPool (tSimplePoly* const poly, int maxNumVoices, tMempool* const pool);
410+
411+
412+ //! Free a tPoly from a specified mempool.
413+ /*!
414+ @param poly A pointer to the tPoly to be freed.
415+ @param pool A pointer to the tMempool from which the tPoly should be freed.
416+ */
417+ void tSimplePoly_freeFromPool (tSimplePoly* const poly, tMempool* const pool);
418+
419+ //! Add a note with a given velocity to the poly handler.
420+ /*!
421+ @param poly A pointer to the relevant tPoly.
422+ @param note The MIDI note number to add.
423+ @param vel The MIDI velocity of the note to add.
424+ @return The voice that will play the note.
425+ */
426+ int tSimplePoly_noteOn (tSimplePoly* const poly, int note, uint8_t vel);
427+
428+
429+ //! Remove a note from the poly handler.
430+ /*!
431+ @param poly A pointer to the relevant tPoly.
432+ @param note The MIDI note number to remove.
433+ @return The voice that was playing the removed note.
434+ */
435+ int tSimplePoly_noteOff (tSimplePoly* const poly, uint8_t note);
436+
437+
438+ //! Set the number of voices available to play notes.
439+ /*!
440+ @param poly A pointer to the relevant tPoly.
441+ @param numVoices The new number of available voices. Cannot be greater than the max number voices given in tPoly_init().
442+ */
443+ void tSimplePoly_setNumVoices (tSimplePoly* const poly, uint8_t numVoices);
444+
445+ //! Set whether pitch glide over note changes in voices is active.
446+ /*!
447+ @param poly A pointer to the relevant tPoly.
448+ @param isActive Whether pitch glide should be active or not.
449+ */
450+
451+ //! Get the current number of voices available to play notes.
452+ /*!
453+ @param poly A pointer to the relevant tPoly.
454+ @return The current number of voices available to play notes.
455+ */
456+ int tSimplePoly_getNumVoices (tSimplePoly* const poly);
457+
458+ //! Get the number of voices currently playing notes.
459+ /*!
460+ @param poly A pointer to the relevant tPoly.
461+ @return The number of voices currently playing notes.
462+ */
463+ int tSimplePoly_getNumActiveVoices (tSimplePoly* const poly);
464+
465+ //! Get the current MIDI note number of a given voice.
466+ /*!
467+ @param poly A pointer to the relevant tPoly.
468+ @param voice The voice to get the MIDI note number of.
469+ @return The MIDI note number of the given voice.
470+ */
471+
472+ int tSimplePoly_getPitch (tSimplePoly* const poly, uint8_t voice);
473+
474+ //! Get the current MIDI velocity of a given voice.
475+ /*!
476+ @param poly A pointer to the relevant tPoly.
477+ @param voice The voice to get the MIDI velocity of.
478+ @return The current MIDI velocity of the given voice.
479+ */
480+ int tSimplePoly_getVelocity (tSimplePoly* const poly, uint8_t voice);
481+
482+
483+ //! Get the current play state of a given voice.
484+ /*!
485+ @param poly A pointer to the relevant tPoly.
486+ @param voice The voice to get the state of.
487+ @return The current play state of the given voice.
488+ */
489+ int tSimplePoly_isOn (tSimplePoly* const poly, uint8_t voice);
490+
491+ /*! @} */
492+ //==============================================================================
365493
366494 #ifdef __cplusplus
367495 }
LEAF/Src/leaf-effects.c+2−2
@@ -1374,14 +1374,14 @@ float tRetune_getInputPeriod(tRetune* const rt) · 1373 unmodified lines
13741374 {
13751375 _tRetune* r = *rt;
13761376
1377− return r->inputPeriod;
1377+ return (r->inputPeriod * leaf.invSampleRate);
13781378 }
13791379
13801380 float tRetune_getInputFreq(tRetune* const rt)
13811381 {
13821382 _tRetune* r = *rt;
13831383
1384− return 1.0f/r->inputPeriod;
1384+ return 1.0f/(r->inputPeriod * leaf.invSampleRate);
13851385 }
13861386
13871387 //============================================================================================================
LEAF/Src/leaf-midi.c+195−0
@@ -679,3 +679,198 @@ int tPoly_isOn(tPoly* const polyh, uint8_t voice) · 678 unmodified lines
679679 _tPoly* poly = *polyh;
680680 return (poly->voices[voice][0] > 0) ? 1 : 0;
681681 }
682+
683+
684+
685+//tSimplePoly = more efficient implementation without ramps and glide
686+
687+
688+// SIMPLE POLY
689+void tSimplePoly_init(tSimplePoly* const polyh, int maxNumVoices)
690+{
691+ tSimplePoly_initToPool(polyh, maxNumVoices, &leaf.mempool);
692+}
693+
694+void tSimplePoly_free(tSimplePoly* const polyh)
695+{
696+ tSimplePoly_freeFromPool(polyh, &leaf.mempool);
697+}
698+
699+void tSimplePoly_initToPool (tSimplePoly* const polyh, int maxNumVoices, tMempool* const mp)
700+{
701+ _tMempool* m = *mp;
702+ _tSimplePoly* poly = *polyh = (_tSimplePoly*) mpool_alloc(sizeof(_tSimplePoly), m);
703+
704+ poly->numVoices = maxNumVoices;
705+ poly->maxNumVoices = maxNumVoices;
706+
707+ for (int i = 0; i < 128; i++)
708+ {
709+ poly->notes[i][0] = -1;
710+ poly->notes[i][1] = 0;
711+ }
712+
713+ poly->voices = (int**) mpool_alloc(sizeof(int*) * poly->maxNumVoices, m);
714+
715+ for (int i = 0; i < poly->maxNumVoices; ++i)
716+ {
717+ poly->voices[i] = (int*) mpool_alloc(sizeof(int) * 3, m);
718+ poly->voices[i][0] = -1;
719+ }
720+ tStack_initToPool(&poly->stack, mp);
721+
722+}
723+
724+void tSimplePoly_freeFromPool (tSimplePoly* const polyh, tMempool* const mp)
725+{
726+ _tMempool* m = *mp;
727+ _tSimplePoly* poly = *polyh;
728+
729+ for (int i = 0; i < poly->maxNumVoices; i++)
730+ {
731+ mpool_free(poly->voices[i], m);
732+ }
733+ tStack_freeFromPool(&poly->stack, mp);
734+ mpool_free(poly->voices, m);
735+ mpool_free(poly, m);
736+}
737+
738+int tSimplePoly_noteOn(tSimplePoly* const polyh, int note, uint8_t vel)
739+{
740+ _tSimplePoly* poly = *polyh;
741+ int whichVoice, whichNote, oldNote, alteredVoice;
742+ // if not in keymap or already on stack, dont do anything. else, add that note.
743+ if (tStack_contains(&poly->stack, note) >= 0) return -1;
744+ else
745+ {
746+ tStack_add(&poly->stack, note);
747+
748+ alteredVoice = -1;
749+ oBool found = OFALSE;
750+ for (int i = 0; i < poly->numVoices; i++)
751+ {
752+ if (poly->voices[i][0] < 0) // if inactive voice, give this note to voice
753+ {
754+
755+ found = OTRUE;
756+
757+ poly->voices[i][0] = note;
758+ poly->voices[i][1] = vel;
759+ poly->notes[note][0] = i;
760+
761+ poly->voices[i][2] = note; // voices[i][2] is the output midi note, (avoiding the -1 when a voice is inactive)
762+
763+ alteredVoice = i;
764+ break;
765+ }
766+ }
767+
768+ if (!found) //steal
769+ {
770+ for (int j = tStack_getSize(&poly->stack) - 1; j >= 0; j--)
771+ {
772+ whichNote = tStack_get(&poly->stack, j);
773+ whichVoice = poly->notes[whichNote][0];
774+ if (whichVoice >= 0)
775+ {
776+ oldNote = poly->voices[whichVoice][0];
777+ poly->voices[whichVoice][0] = note;
778+ poly->voices[whichVoice][1] = vel;
779+ poly->notes[oldNote][0] = -1; //mark the stolen voice as inactive (in the second dimension of the notes array)
780+ poly->notes[note][0] = whichVoice;
781+ poly->notes[note][1] = vel;
782+
783+ poly->voices[whichVoice][2] = note;
784+
785+ alteredVoice = whichVoice;
786+
787+ break;
788+ }
789+ }
790+ }
791+ return alteredVoice;
792+ }
793+}
794+
795+
796+
797+
798+int tSimplePoly_noteOff(tSimplePoly* const polyh, uint8_t note)
799+{
800+ _tSimplePoly* poly = *polyh;
801+ int16_t noteToTest = -1;
802+
803+
804+ tStack_remove(&poly->stack, note);
805+ poly->notes[note][0] = -1;
806+
807+
808+ int deactivatedVoice = -1;
809+ for (int i = 0; i < poly->maxNumVoices; i++)
810+ {
811+ if (poly->voices[i][0] == note)
812+ {
813+ poly->voices[i][0] = -1;
814+ poly->voices[i][1] = 0;
815+ deactivatedVoice = i;
816+ break;
817+ }
818+ }
819+
820+ //grab old notes off the stack if there are notes waiting to replace the free voice
821+ if (deactivatedVoice >= 0)
822+ {
823+ for (int j = 0; j < tStack_getSize(&poly->stack); ++j)
824+ {
825+ noteToTest = tStack_get(&poly->stack, j);
826+
827+ if (poly->notes[noteToTest][0] < 0) //if there is a stolen note waiting (marked inactive but on the stack)
828+ {
829+ poly->voices[deactivatedVoice][0] = noteToTest; //set the newly free voice to use the old stolen note
830+ poly->voices[deactivatedVoice][1] = poly->notes[noteToTest][1]; // set the velocity of the voice to be the velocity of that note
831+ poly->voices[deactivatedVoice][2] = noteToTest;
832+ poly->notes[noteToTest][0] = deactivatedVoice; //mark that it is no longer stolen and is now active
833+ return -1;
834+ }
835+ }
836+ }
837+ return deactivatedVoice;
838+}
839+
840+void tSimplePoly_setNumVoices(tSimplePoly* const polyh, uint8_t numVoices)
841+{
842+ _tSimplePoly* poly = *polyh;
843+ poly->numVoices = (numVoices > poly->maxNumVoices) ? poly->maxNumVoices : numVoices;
844+}
845+
846+
847+int tSimplePoly_getNumVoices(tSimplePoly* const polyh)
848+{
849+ _tSimplePoly* poly = *polyh;
850+ return poly->numVoices;
851+}
852+
853+int tSimplePoly_getNumActiveVoices(tSimplePoly* const polyh)
854+{
855+ _tSimplePoly* poly = *polyh;
856+ return LEAF_clip(0, tStack_getSize(&poly->stack), poly->numVoices);
857+}
858+
859+
860+int tSimplePoly_getPitch(tSimplePoly* const polyh, uint8_t voice)
861+{
862+ _tSimplePoly* poly = *polyh;
863+ return poly->voices[voice][2];
864+}
865+
866+int tSimplePoly_getVelocity(tSimplePoly* const polyh, uint8_t voice)
867+{
868+ _tSimplePoly* poly = *polyh;
869+ return poly->voices[voice][1];
870+}
871+
872+int tSimplePoly_isOn(tSimplePoly* const polyh, uint8_t voice)
873+{
874+ _tSimplePoly* poly = *polyh;
875+ return (poly->voices[voice][0] > 0) ? 1 : 0;
876+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t