Exemple #1
0
                public ReceiveDiff(Song.Receive a, Song.Receive b, int index)
                {
                    this.a     = a;
                    this.b     = b;
                    this.index = index;

                    sendingTrackIndex     = a.SendingTrackIndex != b.SendingTrackIndex;
                    receivingChannelIndex = a.ReceivingChannelIndex != b.ReceivingChannelIndex;
                    volume = a.Volume != b.Volume;
                }
Exemple #2
0
        public Song Process(Project project, ILog logger)
        {
            this.logger  = logger;
            this.project = project;

            var song = new Song();

            song.Tempo      = (int)project.Tempo;
            song.SampleRate = 44100;
            sampleRate      = song.SampleRate;
            tempo           = song.Tempo;

            song.Length = GetSongLength();

            // remove unwanted insert channels
            for (var i = 1; i < project.Inserts.Length; i++)
            {
                var insert = project.Inserts[i];
                if (!IsInsertUsed(insert))
                {
                    project.Inserts[i] = null;
                }
            }

            // deal with sends and routing

            // master track is insert channel 0
            var master = project.Inserts[0];

            // add both insert and channel tracks
            trackReceives = new Dictionary <object, List <FLReceive> >();
            foreach (var projectTrack in project.Inserts)
            {
                if (projectTrack != null)
                {
                    trackReceives.Add(projectTrack, new List <FLReceive>());
                }
            }
            foreach (var channel in project.Channels)
            {
                if (channel.Data is GeneratorData)
                {
                    trackReceives.Add(channel, new List <FLReceive>());
                }
            }

            // link insert track routes
            foreach (var projectTrack in this.project.Inserts)
            {
                if (projectTrack == null)
                {
                    continue;
                }

                for (int i = 0; i < projectTrack.Routes.Length; i++)
                {
                    if (projectTrack.Routes[i])
                    {
                        // route enabled
                        var    sendTrack    = project.Inserts[i];
                        var    channelIndex = projectTrack.RouteVolumes[i] == 0 ? 2 : 0; // very odd but sidechains are volume 0 which means 1 volume
                        double volume       = 1;
                        if (projectTrack.RouteVolumes[i] > 0)
                        {
                            volume = (double)projectTrack.RouteVolumes[i] / 12800;
                        }

                        trackReceives[sendTrack].Add(new FLReceive(projectTrack, channelIndex, volume));
                    }
                }
            }

            // link channel track routes
            foreach (var channel in project.Channels)
            {
                if (channel.Data is GeneratorData)
                {
                    var genData = (GeneratorData)channel.Data;
                    var insert  = project.Inserts[genData.Insert];
                    trackReceives[insert].Add(new FLReceive(channel, 0, genData.Volume / 10000));  // no idea why FL decided on two different volume types!
                }
            }

            visitedTracks = new List <object>();
            orderedTracks = new List <object>();

            // visit master to order tracks using DFS
            VisitTrack(master);

            var projectTracksToSongTracks = new Dictionary <object, Song.Track>();

            foreach (var projectTrack in orderedTracks)
            {
                var track = ConvertTrack(projectTrack);
                projectTracksToSongTracks.Add(projectTrack, track);
                song.Tracks.Add(track);
            }

            // convert each tracks data
            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);
        }
        public Song.Track CreateTrack(ReaperTrack reaperTrack)
        {
            var track = new Song.Track();

            track.Name   = reaperTrack.TrackName;
            track.Volume = reaperTrack.VolumePanning.Volume;

            if (reaperTrack.VolumePanning.Pan != 0)
            {
                logger.WriteLine("WARNING: Pan value {0} on track {1} unsupported", reaperTrack.VolumePanning.Pan, reaperTrack.TrackName);
            }

            // add receives
            foreach (var r in reaperTrack.Receives)
            {
                if (r.ReceiveFader != ReaperFader.PostFader)
                {
                    logger.WriteLine("WARNING: Receive fader type of {0} on track {1} unsupported", r.ReceiveFader, reaperTrack.TrackName);
                }

                var receive = new Song.Receive();
                receive.SendingTrackIndex     = r.ReceiveTrackId + 1;   // master always zero, so tracks are out by one
                receive.ReceivingChannelIndex = r.DestinationChannelIndex;
                receive.Volume = r.Volume;
                track.Receives.Add(receive);
            }

            foreach (var f in reaperTrack.EffectsChain)
            {
                if (f.Wet != 0)
                {
                    logger.WriteLine("WARNING: Wet value for effect {0} on track {1} unsupported", f.Vst.VstFile, reaperTrack.TrackName);
                }

                Song.Device device = null;

                Song.DeviceId deviceId;
                if (Enum.TryParse <Song.DeviceId>(f.Vst.VstFile.Replace(".dll", "").Replace(".64", ""), out deviceId))
                {
                    device       = new Song.Device();
                    device.Id    = deviceId;
                    device.Chunk = f.Vst.VstChunkData;
                }
                if (device == null)
                {
                    logger.WriteLine("WARNING: Device skipped (unsupported plugin): " + f.Vst.VstFile);
                }

                /*else if (f.Vst.Bypass)  // TODO: Parse out Bypass
                 * {
                 *  logger.WriteLine("WARNING: Device skipped (bypass enabled): " + projectDevice.PluginDll);
                 * }*/

                track.Devices.Add(device);
                var deviceIndex = track.Devices.IndexOf(device);
                foreach (var a in f.Automations)
                {
                    track.Automations.Add(ConvertAutomation(a, deviceIndex, reaperTrack.TrackName));
                }

                track.Events = ConvertMidi(reaperTrack.MediaItems);
            }

            return(track);
        }
Exemple #4
0
        public Song Process(LiveProject project, ILog logger)
        {
            this.logger = logger;

            var song = new Song();

            song.Tempo      = (int)project.Tempo;
            song.SampleRate = 44100;

            var projectLoopEnd = project.LoopStart + project.LoopLength;

            trackReceives = new Dictionary <LiveProject.Track, List <Receive> >();
            foreach (var projectTrack in project.Tracks)
            {
                trackReceives.Add(projectTrack, new List <Receive>());
            }
            foreach (var projectTrack in project.Tracks)
            {
                foreach (var send in projectTrack.Sends)
                {
                    if (send.IsActive)
                    {
                        trackReceives[send.ReceivingTrack].Add(new Receive(projectTrack, send.ReceivingChannelIndex - 1, send.Volume));
                    }
                }
            }

            project.MasterTrack.Name = project.MasterTrack.Name == "" ? "Master" : project.MasterTrack.Name;

            visitedTracks = new List <LiveProject.Track>();
            orderedTracks = new List <LiveProject.Track>();

            visitTrack(project.MasterTrack);

            var projectTracksToSongTracks = new Dictionary <LiveProject.Track, Song.Track>();
            var songTrackEvents           = new Dictionary <Song.Track, List <Event> >();

            double?minEventTime = null;
            double?maxEventTime = null;

            foreach (var projectTrack in orderedTracks)
            {
                var track = new Song.Track();
                track.Name   = projectTrack.Name;
                track.Volume = (float)projectTrack.Volume;

                foreach (var projectDevice in projectTrack.Devices)
                {
                    Song.Device device = null;

                    Song.DeviceId deviceId;
                    if (Enum.TryParse <Song.DeviceId>(projectDevice.PluginDll.Replace(".dll", "").Replace(".64", ""), out deviceId))
                    {
                        device       = new Song.Device();
                        device.Id    = deviceId;
                        device.Chunk = projectDevice.RawData != null ? (byte[])projectDevice.RawData.Clone() : new byte[0];
                    }
                    if (device == null)
                    {
                        logger.WriteLine("WARNING: Device skipped (unsupported plugin): " + projectDevice.PluginDll);
                    }
                    else if (projectDevice.Bypass)
                    {
                        logger.WriteLine("WARNING: Device skipped (bypass enabled): " + projectDevice.PluginDll);
                    }
                    else
                    {
                        track.Devices.Add(device);

                        foreach (var floatParameter in projectDevice.FloatParameters)
                        {
                            if (floatParameter.Id >= 0)
                            {
                                var automation = new Song.Automation();
                                automation.DeviceIndex = track.Devices.IndexOf(device);
                                automation.ParamId     = floatParameter.Id;
                                foreach (var e in floatParameter.Events)
                                {
                                    if (e.Time >= 0.0)
                                    {
                                        var point = new Song.Point();
                                        point.TimeStamp = secondsToSamples(e.Time, (double)song.Tempo, (double)song.SampleRate);
                                        point.Value     = e.Value;
                                        automation.Points.Add(point);
                                    }
                                }
                                if (automation.Points.Count > 0)
                                {
                                    track.Automations.Add(automation);
                                }
                            }
                        }
                    }
                }

                var events = new List <Event>();
                foreach (var midiClip in projectTrack.MidiClips)
                {
                    if (!midiClip.IsDisabled)
                    {
                        var loopLength = midiClip.LoopEnd - midiClip.LoopStart;
                        for (var currentTime = midiClip.CurrentStart; currentTime < midiClip.CurrentEnd; currentTime += loopLength)
                        {
                            foreach (var keyTrack in midiClip.KeyTracks)
                            {
                                foreach (var note in keyTrack.Notes)
                                {
                                    if (note.IsEnabled)
                                    {
                                        var startTime = note.Time - (currentTime - midiClip.CurrentStart) - midiClip.LoopStartRelative;
                                        while (startTime < 0.0)
                                        {
                                            startTime += loopLength;
                                        }
                                        startTime = currentTime + startTime - midiClip.LoopStart;
                                        var endTime = startTime + note.Duration;

                                        if ((startTime >= midiClip.CurrentStart && startTime < midiClip.CurrentEnd) &&
                                            (!project.IsLoopOn || (
                                                 startTime >= project.LoopStart && startTime < projectLoopEnd)))
                                        {
                                            endTime = Math.Min(endTime, midiClip.CurrentEnd);
                                            if (project.IsLoopOn)
                                            {
                                                endTime = Math.Min(endTime, projectLoopEnd);
                                            }
                                            if (endTime > startTime)
                                            {
                                                var startEvent = new Event();
                                                startEvent.Time     = startTime;
                                                startEvent.Type     = Song.EventType.NoteOn;
                                                startEvent.Note     = (byte)keyTrack.MidiKey;
                                                startEvent.Velocity = (byte)note.Velocity;
                                                events.Add(startEvent);

                                                var endEvent = new Event();
                                                endEvent.Time = endTime;
                                                endEvent.Type = Song.EventType.NoteOff;
                                                endEvent.Note = (byte)keyTrack.MidiKey;
                                                events.Add(endEvent);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                events.Sort((a, b) =>
                {
                    if (a.Time > b.Time)
                    {
                        return(1);
                    }
                    if (a.Time < b.Time)
                    {
                        return(-1);
                    }
                    if (a.Type == Song.EventType.NoteOn && b.Type == Song.EventType.NoteOff)
                    {
                        return(1);
                    }
                    if (a.Type == Song.EventType.NoteOff && b.Type == Song.EventType.NoteOn)
                    {
                        return(-1);
                    }
                    return(0);
                });
                foreach (var e in events)
                {
                    if (!minEventTime.HasValue || e.Time < minEventTime.Value)
                    {
                        minEventTime = e.Time;
                    }
                    if (!maxEventTime.HasValue || e.Time > maxEventTime.Value)
                    {
                        maxEventTime = e.Time;
                    }
                }

                projectTracksToSongTracks.Add(projectTrack, track);
                songTrackEvents.Add(track, events);
                song.Tracks.Add(track);
            }

            double songStartTime, songEndTime;

            if (project.IsLoopOn)
            {
                songStartTime = project.LoopStart;
                songEndTime   = projectLoopEnd;
            }
            else if (minEventTime.HasValue && maxEventTime.HasValue)
            {
                songStartTime = minEventTime.Value;
                songEndTime   = maxEventTime.Value;
            }
            else
            {
                throw new Exception("Couldn't find song start/end times");
            }
            song.Length = (songEndTime - songStartTime) * 60.0 / (double)song.Tempo;

            foreach (var kvp in songTrackEvents)
            {
                var track  = kvp.Key;
                var events = kvp.Value;

                int lastTimeStamp = 0;
                foreach (var e in events)
                {
                    var songEvent = new Song.Event();
                    var time      = e.Time - songStartTime;
                    int timeStamp = Math.Max(secondsToSamples(time, (double)song.Tempo, (double)song.SampleRate), lastTimeStamp);

                    songEvent.TimeStamp = secondsToSamples(time, (double)song.Tempo, (double)song.SampleRate);
                    songEvent.Type      = e.Type;
                    songEvent.Note      = e.Note;
                    songEvent.Velocity  = e.Velocity;
                    track.Events.Add(songEvent);
                    lastTimeStamp = timeStamp;
                }
            }

            // TODO: Clip all of this instead of just offsetting
            // adjust automation start times based on song start
            foreach (var track in song.Tracks)
            {
                foreach (var automation in track.Automations)
                {
                    foreach (var point in automation.Points)
                    {
                        point.TimeStamp -= secondsToSamples(songStartTime, (double)song.Tempo, (double)song.SampleRate);
                    }
                }
            }

            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);
        }
        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);
        }