public void ExportSong() { // Get the active song data var songData = musicChip.trackerDataCollection[patterns[currentPattern]]; var totalNotesRendered = 0; int tracknum; int notenum; int gotANote; var tcount = songData.tracks.Length; var ncount = songData.tracks[0].notes.Length; var totalNotesInSong = ncount; // total musical notes in song loops x notes note_tick_s = 15.0f / songData.speedInBPM; // (15.0f/120.0f) = 120BPM sixteenth notes note_tick_s_odd = note_tick_s * swing_rhythm_factor; // small beat var notedatalength = (int)(preRenderBitrate * 2f * note_tick_s_odd); // one note worth of stereo audio (x2) // TODO this is off. It is happening to fast and not matching up to the correct speed of the song. var beatlength = preRenderBitrate * note_tick_s_odd; // one note worth of time var songdatalength = notedatalength * totalNotesInSong; // stereo cd quality x song length var notebuffer = new float[notedatalength]; if (trackresult == null) { // all the tracks we need - an array of audioclips that will be merged into result trackresult = new RawAudioData[tcount]; for (var i = 0; i < tcount; i++) { trackresult[i] = new RawAudioData(0, 1, preRenderBitrate); } } var instrument = new SfxrSynth[songData.totalTracks]; var newStartPos = trackresult[0].samples / 2; var newLength = trackresult[0].samples + songdatalength; for (tracknum = 0; tracknum < tcount; tracknum++) { if (instrument[tracknum] == null) { instrument[tracknum] = new SfxrSynth(); } var songdataCurrentPos = newStartPos; trackresult[tracknum].Resize(newLength); // set the params to current track's instrument string instrument[tracknum].parameters .SetSettingsString(soundChip.ReadSound(songData.tracks[tracknum].sfxID).param); // Loop through all of the notes in the track for (notenum = 0; notenum < ncount; notenum++) { // what note is it? gotANote = songData.tracks[tracknum].notes[notenum]; // generate one note worth of audio data if (gotANote > 0 && instrument[tracknum] != null) { //instrument[tracknum].Reset(true); // seems to do nothing // doing this for every note played is insane: // try a fresh new instrument (RAM and GC spammy) instrument[tracknum] = new SfxrSynth(); // shouldn't be required, but for some reason it is // set the params to current track's instrument string instrument[tracknum].parameters .SetSettingsString(soundChip.ReadSound(songData.tracks[tracknum].sfxID).param); // pitch shift the sound to the correct musical note frequency instrument[tracknum].parameters.startFrequency = noteStartFrequency[gotANote]; // maybe this will help // instrument[tracknum].GenerateAudioFilterData(float[] __data, int __channels) // or perhaps this - nope: outputs silence... hmm //bool gotAllData = instrument[tracknum].SynthWave(notebuffer, 0, (uint)notedatalength);// (uint)notebuffer.Length); // unlikely but helpful - used by GenerateAudioFilterData // WriteSamples(float[] __originSamples, int __originPos, float[] __targetSamples, int __targetChannels) { // Writes raw samples to Unity's format and return number of samples actually written // does play need to be called for it to be generated properly? instrument[tracknum].CacheSound(); // generate cachedWave data // grab the sample data - this data is not in the same fmt as unity's internal? // sounds pitch-shifted and faster - a different bitrate? // WORKS GREAT IF WE RUN CACHESOUND() FIRST // TODO need to figure out why we can't access the cachedWave notebuffer = instrument[tracknum].data; // the wave data for the current note // this SHOULD be the solution. but outputs all 0's //bool gotAllData = instrument[tracknum].GenerateAudioFilterData(notebuffer, 2); // move sound data into audioclip buffer if (notebuffer != null && notebuffer.Length > 0) { trackresult[tracknum].SetData(notebuffer, songdataCurrentPos); } // else // Debug.LogWarning("Notebuffer was blank. Ignoring."); totalNotesRendered++; } // TODO converted this to an int, may break? songdataCurrentPos += (int)beatlength; //notedatalength; this is x2 due to stereo //yield return null; // if here, min one frame PER note PER track PER loop: too slow } // for all notes } // for all tracks currentPattern++; currentStep++; }