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
362 /*! @} */362 /*! @} */
363 363
364 //==============================================================================364 //==============================================================================
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 //==============================================================================
365 493
366#ifdef __cplusplus494#ifdef __cplusplus
367}495}
LEAF/Src/leaf-effects.c+2−2
@@ -1374,14 +1374,14 @@ float tRetune_getInputPeriod(tRetune* const rt) · 1373 unmodified lines
1374{1374{
1375 _tRetune* r = *rt;1375 _tRetune* r = *rt;
1376 1376
1377 return r->inputPeriod;1377 return (r->inputPeriod * leaf.invSampleRate);
1378}1378}
1379 1379
1380float tRetune_getInputFreq(tRetune* const rt)1380float tRetune_getInputFreq(tRetune* const rt)
1381{1381{
1382 _tRetune* r = *rt;1382 _tRetune* r = *rt;
1383 1383
1384 return 1.0f/r->inputPeriod;1384 return 1.0f/(r->inputPeriod * leaf.invSampleRate);
1385}1385}
1386 1386
1387//============================================================================================================1387//============================================================================================================
LEAF/Src/leaf-midi.c+195−0
@@ -679,3 +679,198 @@ int tPoly_isOn(tPoly* const polyh, uint8_t voice) · 678 unmodified lines
679 _tPoly* poly = *polyh;679 _tPoly* poly = *polyh;
680 return (poly->voices[voice][0] > 0) ? 1 : 0;680 return (poly->voices[voice][0] > 0) ? 1 : 0;
681}681}
682
683
684
685//tSimplePoly = more efficient implementation without ramps and glide
686
687
688// SIMPLE POLY
689void tSimplePoly_init(tSimplePoly* const polyh, int maxNumVoices)
690{
691 tSimplePoly_initToPool(polyh, maxNumVoices, &leaf.mempool);
692}
693
694void tSimplePoly_free(tSimplePoly* const polyh)
695{
696 tSimplePoly_freeFromPool(polyh, &leaf.mempool);
697}
698
699void 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
724void 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
738int 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
798int 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
840void 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
847int tSimplePoly_getNumVoices(tSimplePoly* const polyh)
848{
849 _tSimplePoly* poly = *polyh;
850 return poly->numVoices;
851}
852
853int tSimplePoly_getNumActiveVoices(tSimplePoly* const polyh)
854{
855 _tSimplePoly* poly = *polyh;
856 return LEAF_clip(0, tStack_getSize(&poly->stack), poly->numVoices);
857}
858
859
860int tSimplePoly_getPitch(tSimplePoly* const polyh, uint8_t voice)
861{
862 _tSimplePoly* poly = *polyh;
863 return poly->voices[voice][2];
864}
865
866int tSimplePoly_getVelocity(tSimplePoly* const polyh, uint8_t voice)
867{
868 _tSimplePoly* poly = *polyh;
869 return poly->voices[voice][1];
870}
871
872int 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