Beispiel #1
0
        public ITFHeader ToITF()
        {
            ITFHeader result = new ITFHeader();

            result.BeatPerMinute = Header.DefaultBPM;
            result.TickPerRow    = Header.DefaultTempo;

            foreach (var pat in Patterns)
            {
                ITFPattern itfp         = new ITFPattern();
                bool       emptypattern = true;
                for (int row = 0; row < pat.NumberOfRows; row++)
                {
                    ITFRow itfr     = new ITFRow();
                    bool   emptyrow = true;
                    for (int channel = 0; channel < Header.NumberOfChannels; channel++)
                    {
                        XMNote  xmnote = pat.PatArr[row, channel];
                        ITFNote itfn   = null;

                        if (xmnote != null)
                        {
                            emptyrow     = false;
                            emptypattern = false;
                            itfn         = new ITFNote();
                            if (xmnote.Instrument != 0)
                            {
                                itfn.Instrument = xmnote.Instrument;
                            }
                            if (xmnote.Note != 0)
                            {
                                itfn.Note = xmnote.Note;
                            }
                            itfn.Volume      = xmnote.Volume;
                            itfn.NoteOff     = xmnote.noteoff;
                            itfn.Effect      = xmnote.Effect;
                            itfn.EffectParam = xmnote.EffectParam;
                        }
                        itfr.Channels.Add(itfn);
                    }
                    if (emptyrow)
                    {
                        itfr = null;
                    }
                    itfp.Rows.Add(itfr);
                }
                if (emptypattern)
                {
                    itfp = null;
                }
                result.Patterns.Add(itfp);
            }

            foreach (byte item in Header.PatternOrderTable)
            {
                result.PlayOrder.Add(result.Patterns[item]);
            }

            return(result);
        }
Beispiel #2
0
        public static List <byte> PatternToBytes(this ITFPattern itfpattern, Conversion conv, bool[] channelson = null, int?FromRow = null, int?ToRow = null)
        {
            int usedchannels = Math.Min(itfpattern.Rows.Max(x => x.Channels.Count), 8);

            if (channelson == null)
            {
                channelson = new bool[usedchannels];
                for (int i = 0; i < channelson.Length; i++)
                {
                    channelson[i] = true;
                }
            }

            List <byte> bytes = new List <byte>();
            byte        register, value = 0;

            for (int rows = 0; rows < itfpattern.Rows.Count; rows++)
            {
                if (FromRow.HasValue && FromRow.Value > rows)
                {
                    continue;
                }
                if (ToRow.HasValue && ToRow.Value < rows)
                {
                    continue;
                }

                //Is there any effects needs ticking here?
                bool tickingneeded = false;
                for (int channels = 0; channels < itfpattern.Rows[rows].Channels.Count; channels++)
                {
                    ITFNote cn = itfpattern.Rows[rows].Channels[channels];
                    //Tempo determination. This can come from all available channels.
                    if (cn.Effect == 0xF)
                    {
                        if (cn.EffectParam < 32)
                        {
                            conv.CurrentTickPerRow = cn.EffectParam.Value;
                        }
                        else
                        {
                            conv.CurrentBPM = cn.EffectParam.Value;
                        }
                    }

                    //Ticking will apply only for the phisycally converted channels.
                    if (channels > usedchannels)
                    {
                        continue;
                    }
                    int epu = ((byte)cn.EffectParam.Value >> 4) & 0xF;
                    int epd = (byte)cn.EffectParam.Value & 0xF;
                    tickingneeded =
                        tickingneeded ||
                        (cn.Effect == 0xE && epu == 0xD) ||
                        (cn.Effect == 0xE && epu == 0xC) ||
                        (cn.Effect == 0xA && cn.EffectParam != 0);
                }

                if (tickingneeded)
                {
                    ITFNote[,] tickarr = new ITFNote[conv.CurrentTickPerRow, usedchannels];

                    for (int channel = 0; channel < usedchannels; channel++)
                    {
                        if (!channelson[channel])
                        {
                            continue;
                        }

                        ITFNote cn  = itfpattern.Rows[rows].Channels[channel];
                        int     epu = ((byte)cn.EffectParam.Value >> 4) & 0xF;
                        int     epd = (byte)cn.EffectParam.Value & 0xF;

                        if (cn.Effect == 0xA && cn.EffectParam != 0) //Volume slide
                        {
                            tickarr[0, channel] = cn;
                            int volume = cn.Volume.Value;
                            int diff   = -epd;
                            if (epu != 0)
                            {
                                diff = epu;
                            }

                            for (int i = 1; i < conv.CurrentTickPerRow; i++)
                            {
                                volume += diff;
                                if (volume < 0)
                                {
                                    volume = 0;
                                }
                                if (volume > 64)
                                {
                                    volume = 64;
                                }
                                tickarr[i, channel] = new ITFNote()
                                {
                                    Volume = (byte)volume
                                };
                            }
                        }
                        else if (cn.Effect == 0xE && epu == 0xD)
                        {
                            if (epd > 5)
                            {
                                epd = 5;
                            }
                            tickarr[epd, channel] = cn;
                        }
                        else if (cn.Effect == 0xE && epu == 0xC) //Note cut
                        {
                            if (epd > 5)
                            {
                                epd = 5;
                            }
                            tickarr[0, channel]   = cn;
                            tickarr[epd, channel] = new ITFNote()
                            {
                                NoteOff = true
                            };
                        }
                        else
                        {
                            tickarr[0, channel] = cn;
                        }
                    }

                    for (int ticks = 0; ticks < conv.CurrentTickPerRow; ticks++)
                    {
                        for (int channel = 0; channel < usedchannels; channel++)
                        {
                            if (!channelson[channel])
                            {
                                continue;
                            }
                            ITFNote cn = tickarr[ticks, channel];
                            if (cn != null)
                            {
                                NoteIntoBytes(cn, bytes, channel, conv);
                            }
                        }
                        //Timing
                        register = 0;
                        value    = (byte)bpmtoplayertick(conv);
                        addtobytes(bytes, register, value, conv.CYMS);
                    }
                }
                else
                {
                    for (int channel = 0; channel < usedchannels; channel++)
                    {
                        if (!channelson[channel])
                        {
                            continue;
                        }
                        ITFNote cn = itfpattern.Rows[rows].Channels[channel];
                        NoteIntoBytes(cn, bytes, channel, conv);
                    }
                    //Timing
                    register = 0;
                    value    = (byte)bpmtoplayertickrow(conv);
                    addtobytes(bytes, register, value, conv.CYMS);
                }
            }
            return(bytes);
        }