Wave Layering

General discussion about tracking, help and support.
User avatar
beachbum811
Posts: 104
Joined: Thu Jul 28, 2016 2:19 pm

Wave Layering

Postby beachbum811 » Thu Aug 25, 2016 11:46 pm

I guess I'm coining that term.
Just to prove it's possible:

I have no idea why I did this.
Credit to the owners of these songs, blah blah blah
Double Wave.ftm
(4.56 KiB) Downloaded 152 times

EDIT 1: Now the pitches are changed so that the note input is always the bottom note in the interval
EDIT 2: Approximated minor second and tritone waves
EDIT 3: Tuned the waves a bit better
Last edited by beachbum811 on Fri Aug 26, 2016 8:55 pm, edited 6 times in total.
Hello World!
Behold as I run facefirst into the endless abyss of hate that is the internet!
I do Musescore and Scratch with the same username!

OH and I also use beta 0.5 so...

User avatar
Teuthida
Posts: 534
Joined: Sun Apr 24, 2016 2:25 am

Re: Wave Layering

Postby Teuthida » Fri Aug 26, 2016 12:35 am

Pretty neat! Does it work with other waveforms?
A squid with a higher post count than the NES can handle.

I'm on YouTube! https://www.youtube.com/channel/UCX87jJAJ3LPezjkWIk2TWEg

User avatar
HertzDevil
Posts: 475
Joined: Thu Apr 23, 2015 7:39 pm
Location: Hong Kong SAR
Contact:

Re: Wave Layering

Postby HertzDevil » Fri Aug 26, 2016 4:15 am

My take on this, not going to tune the rest of the instruments for each used pitch. (The tuning part is trivial if I do not use the beta build.)

Teuthida wrote:Pretty neat! Does it work with other waveforms?

The square wave can be expressed as a waveform with only 2 samples, any longer and you lose the ability to use the more dissonant intervals. Already I had to fake a pulse wave for the minor second.
Attachments
kriad.05b.ftm
(9.86 KiB) Downloaded 85 times
refactoring 0cc-famitracker

User avatar
beachbum811
Posts: 104
Joined: Thu Jul 28, 2016 2:19 pm

Re: Wave Layering

Postby beachbum811 » Fri Aug 26, 2016 2:08 pm

How did you make the tritone wave?
and the minor second wave, for that matter.
I also noticed that your waves range from 0 - 2 - 6 - 8.
Mine range from 0 - 7 - 14.
Why is this?
Hello World!
Behold as I run facefirst into the endless abyss of hate that is the internet!
I do Musescore and Scratch with the same username!

OH and I also use beta 0.5 so...

User avatar
HertzDevil
Posts: 475
Joined: Thu Apr 23, 2015 7:39 pm
Location: Hong Kong SAR
Contact:

Re: Wave Layering

Postby HertzDevil » Fri Aug 26, 2016 5:38 pm

Tritone is 10:7, minor second is 16:15 (forcibly halved in size, hence the impure pulse waves).

The whole purpose of that module is to perform double-channel echo with one channel, so every wave is composed of a "dry" one at volume 6 and the echo at volume 2. Exchanging the volumes of those two square waves produces the echo instrument transposed in the opposite direction.

It is easy to generate waveforms like that with any scripting language. For example:

Code: Select all

-- greatest common divisor
local function gcd (x, y) return y == 0 and x or gcd(y, x % y) end
-- least common multiple
local lcm = function (x, y) return x * y / gcd(x, y) end

-- map expression for sequences
local function map_t (f, t)
  local z = {}
  for i, v in ipairs(t) do z[i] = f(v) end
  return z
end
-- fold expression
local function foldl (f, x, ...)
  if not ... then return x end
  return foldl(f, f(x, (...)), select(2, ...))
end

local unpack = table.unpack or unpack

-- produces a sum of waveforms
-- wave: table containing wave samples
-- notes: table of notes, which themselves are tables with these entries:
--  - [1] frequency
--  - [2] volume multiplier
--  - [3] phase (optiomal, default 0)
local makechord = function (wave, notes)
  assert(#notes >= 2)
  local s = foldl(lcm, unpack(map_t(function (v) return v[1] end, notes)))
  local period = map_t(function (v) return s / v[1] * #wave end, notes)
  local minsize = foldl(lcm, 4, unpack(period))
 
  local wav = {}
  for t = 0, minsize - 1 do
    local sample = 0
    for i, v in ipairs(notes) do
      local pos = math.floor((t + (v[3] or 0)) * #wave / period[i]) % #wave
      sample = sample + v[2] * wave[pos + 1]
    end
    wav[t + 1] = sample
  end
  return wav
end
Usage:

Code: Select all

-- one cycle of square wave
local cycle = {0, 1}

-- a major chord (4:5:6)
local chord = {
  {4, 5},
  {5, 3},
  {6, 4},
}

-- make it
print(table.concat(makechord(cycle, chord), " "))
Result:

Code: Select all

0 0 0 0 0 0 0 0 0 0 4 4 7 7 7 12 12 12 12 12 8 8 8 8 5 5 5 5 5 5 4 4 4 4 4 4 7 7 7 7 3 3 3 3 3 8 8 8 5 5 9 9 9 9 9 9 9 9 9 9 3 3 3 3 3 3 3 3 3 3 7 7 4 4 4 9 9 9 9 9 5 5 5 5 8 8 8 8 8 8 7 7 7 7 7 7 4 4 4 4 0 0 0 0 0 5 5 5 8 8 12 12 12 12 12 12 12 12 12 12

This is not exactly the script I used to generate those waveforms myself, however, since I used wave periods for each square wave directly.
refactoring 0cc-famitracker

User avatar
beachbum811
Posts: 104
Joined: Thu Jul 28, 2016 2:19 pm

Re: Wave Layering

Postby beachbum811 » Fri Aug 26, 2016 7:04 pm

oh, on mine the volumes are equal.
I used a program to make the strings as well of course.
I think the tritone is 45:32. I think 7:5 is closer to that than 10:7, but thanks for the idea.
Concerning the minor second, I was completely stumped until you helped.
Hello World!
Behold as I run facefirst into the endless abyss of hate that is the internet!
I do Musescore and Scratch with the same username!

OH and I also use beta 0.5 so...