Advertisement
mkv

soundchip sampler

mkv
Apr 29th, 2014
246
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.88 KB | None | 0 0
  1. // written 2014-04-29 by tripflag <ed@irc.rizon.net>
  2. // licensed GPL v2
  3. //
  4. // this program takes a .wave file that contains a monophonic single-instrument,
  5. // playing n notes of t microseconds each followed by t microseconds of silence.
  6. // the notes are sliced into groups, each group is sliced by the period of the note,
  7. // and each period is finally averaged together to generate a perfectly-looping and
  8. // flawless rendition of the soundchip. N output wavefiles for N original notes.
  9.  
  10.         int seg;
  11.         Seg[] segs;
  12.         Seg[][] segc;
  13.         List<Seg> segso;
  14.         byte[] buffer;
  15.         bool painter;
  16.         bool paintBusy;
  17.         int avg1, avg2;
  18.         int span;
  19.  
  20.         void t_Tick(object sender, EventArgs e)
  21.         {
  22.             ((Timer)sender).Stop();
  23.             buffer = System.IO.File.ReadAllBytes("tri.wav"); // because 20MB of RAM is nothing today (deal with it)
  24.             paintBusy = false;
  25.             painter = false;
  26.             long last = 0;
  27.             span = 1;
  28.             seg = 0;
  29.             segso = new List<Seg>();
  30.             panel1.BackgroundImage = null;
  31.             panel2.BackgroundImage = null;
  32.             for (long a = 0; a < buffer.Length; a += 2)
  33.             {
  34.                 // Get amplitude of sample at offset a
  35.                 long v = buffer[a + 1];
  36.                 v += v < 0x80 ? 0x80 : -0x80;
  37.                 v = v * 256 + buffer[a];
  38.  
  39.                 // check whether sample is in the top half of the waveform,
  40.                 // and that the previous sample was in the bottom half
  41.                 if (v > 0x8010 && last < 0x7ff0)
  42.                 {
  43.                     // update current (old) segment with
  44.                     // this sample offset as end position
  45.                     if (segso.Count > 0)
  46.                     {
  47.                         segso[segso.Count - 1].end(a);
  48.                     }
  49.  
  50.                     // add a new segment starting from this offset
  51.                     segso.Add(new Seg(a));
  52.  
  53.                     // update last with current amplitude
  54.                     last = v;
  55.                 }
  56.  
  57.                 // check whether sample is in the bottom half of the waveform
  58.                 if (v < 0x7ff0)
  59.                 {
  60.                     // update sample amplitude regardless
  61.                     last = v;
  62.                 }
  63.             }
  64.  
  65.             // remove 4096 samples at the start of each new note
  66.             for (int a = 0; a < segso.Count; a++)
  67.             {
  68.                 //long prev = segso[a - 1].b - segso[a - 1].a;
  69.                 long cur = segso[a].b - segso[a].a;
  70.                 long next = segso[a].b - segso[a].a;
  71.                 if (cur > 40960 &&
  72.                     next < 40960)
  73.                 {
  74.                     a++;
  75.                     long sum = 0;
  76.                     while (sum < 8192)
  77.                     {
  78.                         Seg s = segso[a];
  79.                         sum += s.b - s.a;
  80.                         segso.RemoveAt(a);
  81.                         a--;
  82.                     }
  83.                 }
  84.             }
  85.  
  86.             // combine short segs so none are shorter than 4096 samples
  87.             List<Seg> rewq = new List<Seg>();
  88.             Seg ts = null;
  89.             for (int a = 0; a < segso.Count; a++)
  90.             {
  91.                 if (ts == null)
  92.                 {
  93.                     //s = segso[a];
  94.                     ts = new Seg(segso[a].a);
  95.                     ts.b = segso[a].b;
  96.                 }
  97.                 else if (ts.b - ts.a < 2048)
  98.                 {
  99.                     ts.b = segso[a].b;
  100.                 }
  101.                 if (ts.b - ts.a >= 2048)
  102.                 {
  103.                     rewq.Add(ts);
  104.                     ts = null;
  105.                 }
  106.             }
  107.             segs = rewq.ToArray();
  108.  
  109.             // create list of seg arrays, note collection
  110.             List<Seg> fdsa = new List<Seg>();
  111.             List<Seg[]> asdf = new List<Seg[]>();
  112.             for (int a = 0; a < segs.Length - 1; a++)
  113.             {
  114.                 //long prev = segso[a - 1].b - segso[a - 1].a;
  115.                 long cur = segs[a+0].b - segs[a+0].a;
  116.                 long next = segs[a+1].b - segs[a+1].a;
  117.                 if (cur > 40960 &&
  118.                     next < 8192)
  119.                 {
  120.                     if (fdsa.Count > 3)
  121.                     {
  122.                         asdf.Add(fdsa.ToArray());
  123.                     }
  124.                     fdsa.Clear();
  125.                 }
  126.                 else if (cur < 8192)
  127.                 {
  128.                     fdsa.Add(segs[a]);
  129.                 }
  130.             }
  131.             asdf.Add(fdsa.ToArray());
  132.             segc = asdf.ToArray();
  133.  
  134.             // find most popular segment length of each note
  135.             for (int a = 0; a < segc.Length; a++)
  136.             {
  137.                 var ddd = segc[a]
  138.                     .GroupBy((s) => s.b - s.a)
  139.                     .Select((f) => new {
  140.                         Len = f.Key,
  141.                         Num = segc[a].Count(
  142.                             (s2) => (s2.b - s2.a) == f.Key
  143.                         )
  144.                     })
  145.                     .OrderBy((aa) => aa.Num).ToList();
  146.  
  147.                 long len = ddd[ddd.Count - 1].Len / 2;
  148.                 ulong[] avg = new ulong[len];
  149.                 for (int i = 0; i < len; i++)
  150.                 {
  151.                     avg[i] = 0;
  152.                 }
  153.                 ulong avgc = 0;
  154.                 for (int i = 0; i < segc[a].Length; i++)
  155.                 {
  156.                     if (len * 2 == segc[a][i].b - segc[a][i].a)
  157.                     {
  158.                         long startFrom = segc[a][i].a;
  159.                         for (long j = 0; j < len * 2; j += 2)
  160.                         {
  161.                             long v = buffer[startFrom + j + 1];
  162.                             v += v < 0x80 ? 0x80 : -0x80;
  163.                             v = v * 256 + buffer[startFrom + j];
  164.                             avg[j / 2] += (ulong)v;
  165.                         }
  166.                         avgc++;
  167.                     }
  168.                 }
  169.                 for (int i = 0; i < len; i++)
  170.                 {
  171.                     avg[i] = avg[i] / avgc;
  172.                     avg[i] = avg[i] < 0x8000 ?
  173.                              avg[i] + 0x8000 :
  174.                              avg[i] - 0x8000;
  175.                 }
  176.                 byte[] data = new byte[len * 2 + 44];
  177.                 Array.Copy(buffer, data, 44);
  178.                 for (var i = 0; i < len; i++)
  179.                 {
  180.                     data[i * 2 + 44] = (byte)(avg[i] % 256);
  181.                     data[i * 2 + 45] = (byte)(avg[i] / 256);
  182.                 }
  183.                 Array.Copy(BitConverter.GetBytes(data.Length - 8), 0, data, 4, 4);
  184.                 Array.Copy(BitConverter.GetBytes(data.Length - 44), 0, data, 40, 4);
  185.                 System.IO.File.WriteAllBytes(string.Format("out\\note{0:d2}.wav", a), data);
  186.             }
  187.         }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement