void Update() { // receive ticks PClock.Update(); // sequence audio PSequencer.Sequencer(); PAudioPlayer.Update(); PParameterLinker.Update(); }
void Start() { PAudioPlayer.Start(); // setup fmod API InitialiseLayers(); // read looping audio entryList = PAutoFileLoader.ReadFiles(folderLocationLoops, amountOfLayers); // read oneshots entryListOS = PAutoFileLoader.ReadFiles(folderLocationOneShots, amountOfSoundEffects, true); PClock.Init(100); PParameterLinker.Start(); }
// read files for looping sounds public static List <List <string> > ReadFiles(string directoryLocation, int layerAmount, bool oneShotsLayers = false) { // TODO: track reading isnt really necessary anymore. could also be moved to end of name to allow for easier filenaming from daws DirectoryInfo dir = new DirectoryInfo(directoryLocation); FileInfo[] info = dir.GetFiles("*.wav*"); // list containing al wav files List <string> fileNames = new List <string>(); // all layers and their info List <List <string> > entryList = new List <List <string> >(); // layer, tracks, filename foreach (FileInfo f in info) { fileNames.Add(f.Name); } // initialise entrylist for (int i = 0; i < layerAmount; i++) { entryList.Add(new List <string>()); } // parse list per filename for (int i = 0; i < fileNames.Count; i++) { // pass name in layer per track to entry list entryList[int.Parse(fileNames[i][0].ToString()) - 1].Add(fileNames[i]); // initialise sounds PAudioPlayer.InitSound(int.Parse(fileNames[i][0].ToString()) - 1, fileNames[i], directoryLocation, oneShotsLayers); } return(entryList); }
// call oneshot sounds public static void playOneShot(int layer, int soundIndex, bool reverse = false, float ducking = 0) { // TODO: add ducking functionality PAudioPlayer.PlayFile(layer, soundIndex, reverse, true); }
public static void Sequencer() { if (PClock.nextTick) { ProceduralAudio.print("tick"); foreach (PCycleTimer cycleTimer in PParameterLinker.cycleTimers) { // check trigger timed cycle if (cycleTimer.currentTick % cycleTimer.lengthInTicks == cycleTimer.lengthInTicks - 1) { if (cycleTimer.cycle != null) { PAudioDataSystem.CallCycle(cycleTimer.cycle); } else { PAudioDataSystem.callDynamicCycle(cycleTimer.dynamicCycle); } } cycleTimer.currentTick += 1; } // for every layer for (int layer = 0; layer < ProceduralAudio.amountOfLayers; layer++) { var currentLayer = ProceduralAudio.layers[layer]; // convert tick number into measure currentLayer.currentTick %= currentLayer.rythm.Count; // check if layer is active if (currentLayer.layerOn) { // check rythm if (currentLayer.rythm[currentLayer.currentTick] == 1) { // TODO: set scale for all layers here instead of only the melody // check if audio needs to adapt to another layer and play audio TODO: set a layer parameter to see if it needs to adapt instead of just checking if its the melody if (currentLayer.layerType == ProceduralAudio.LayerType.melody) { // account for scale having switches int chordBaseScaleIndex = (PAudioDataSystem.currentScale.IndexOf(currentChordBase) == -1) ? PAudioDataSystem.previousScale.IndexOf(currentChordBase) : PAudioDataSystem.currentScale.IndexOf(currentChordBase); PAudioPlayer.PlayFile(layer, PAudioDataSystem.currentScale[(chordBaseScaleIndex + currentLayer.melody[currentLayer.currentTick]) % PAudioDataSystem.currentScale.Count]); } else { PAudioPlayer.PlayFile(layer, currentLayer.melody[currentLayer.currentTick]); } // set currentChord when chordlayer changes if (currentLayer.layerType == ProceduralAudio.LayerType.chords) { currentChordBase = currentLayer.melody[currentLayer.currentTick]; } } } // next tick currentLayer.currentTick += 1; } } }