public Song Process(RenoiseSong project, ILog logger) { this.logger = logger; // hex lookup.. because reasons... for (int i = 0; i <= 255; i++) { hexLookUp.Add(i.ToString("X2"), (byte)i); } this.project = project; var song = new Song(); song.Tempo = (int)this.project.GlobalSongData.BeatsPerMin; song.SampleRate = 44100; secondsPerIndex = (double)song.Tempo * (double)this.project.GlobalSongData.LinesPerBeat; secondsPerIndex = 60 / secondsPerIndex; sampleRate = song.SampleRate; song.Length = GetSongLength(); var master = this.project.Tracks.Items.Where(track => track is SequencerMasterTrack).First(); trackReceives = new Dictionary <object, List <RnsReceive> >(); foreach (var projectTrack in this.project.Tracks.Items) { trackReceives.Add(projectTrack, new List <RnsReceive>()); } // send mapping foreach (var projectTrack in this.project.Tracks.Items) { string trackName = GetProp("Name", projectTrack).ToString(); object[] trackDevices = ((TrackFilterDeviceChain)GetProp("FilterDevices", projectTrack)).Devices.Items; var sends = new List <SendDevice>(); // get all send devices bool found = false; foreach (var device in trackDevices) { if (device is SendDevice) { found = true; sends.Add((SendDevice)device); } if (found && !(device is SendDevice)) { logger.WriteLine("WARNING: Track {0} has device {1} after send", trackName, device); } } foreach (var send in sends) { if (send.MuteSource && sends.IndexOf(send) != sends.Count - 1) { logger.WriteLine("WARNING: Track {0} has muted send which is not the last send in the chain", trackName); } if (send.IsActive.Value == 1 && send.SendAmount.Value > 0) { var sendTrack = GetSendTrack((int)send.DestSendTrack.Value); trackReceives[sendTrack].Add(new RnsReceive(projectTrack, 0, send.SendAmount.Value)); } else { logger.WriteLine("WARNING: Track {0} has disabled send", trackName); } } // track is not master, so find where it goes... if (projectTrack != master) { int routing = (int)GetProp("TrackRouting", projectTrack); if (routing == 0) { // routed to master if (!MutedSend(projectTrack)) // muted send so no actual output { var trackVolume = GetTrackVolume(trackDevices[0]); trackReceives[master].Add(new RnsReceive(projectTrack, 0, trackVolume)); } } else if (routing == -1) { // routed to group track if (!MutedSend(projectTrack)) // muted send so no actual output { var group = GetGroupTrack(projectTrack); var trackVolume = GetTrackVolume(trackDevices[0]); trackReceives[group].Add(new RnsReceive(projectTrack, 0, trackVolume)); } } else { // routed to specific soundcard output logger.WriteLine(string.Format("WARNING: Track {0} routing to soundcard?? WTF!", trackName)); } } } visitedTracks = new List <object>(); orderedTracks = new List <object>(); VisitTrack(master); GetInstruments(); var projectTracksToSongTracks = new Dictionary <object, Song.Track>(); foreach (var projectTrack in orderedTracks) { var track = ConvertTrack(this.project.Tracks.Items.ToList().IndexOf(projectTrack)); projectTracksToSongTracks.Add(projectTrack, track); song.Tracks.Add(track); } foreach (var kvp in projectTracksToSongTracks) { foreach (var projectReceive in trackReceives[kvp.Key]) { if (projectTracksToSongTracks.ContainsKey(projectReceive.SendingTrack)) { var receive = new Song.Receive(); receive.SendingTrackIndex = song.Tracks.IndexOf(projectTracksToSongTracks[projectReceive.SendingTrack]); receive.ReceivingChannelIndex = projectReceive.ReceivingChannelIndex; receive.Volume = (float)projectReceive.Volume; kvp.Value.Receives.Add(receive); } } } return(song); }