-- Display waveform as sequence of changes in amplitude over time -- The main reason I created this system :-) with trace include win32lib.ew without warning include graphex.ew with warning constant WAV_CHANNELS = 1, -- the number of channels (1=mono, 2=stereo etc) WAV_SAMPRATE = 2, -- the number of samples per second (44100 = CD quality) WAV_BITS = 3, -- the number of bits per sample (is always 8, 16 or 24) WAV_LEN = 4, -- the length (duration when played) of the wave (in samples) WAV_DATA = 5 -- the wave data {per, channel} include wavefile.e -- by Daryl Van Den Brink atom win constant TRACK_HEIGHT = 128 constant INFO_HEIGHT = 32 constant TITLE_BAR = 24 sequence track_gfxs -- sequence of gfx objects, one per channel sequence info_gfx track_gfxs = {} info_gfx = {} atom time_s integer end_tick, tick_step, sec atom tscale -- seconds per pixel atom vscale, hscale -- value per pixel sequence label atom voffset,lastv, diff integer val sequence wav_data wav_data = read_wave_file("euphoria_8bit_6k.wav") if length(wav_data) = 0 then puts(1, "Couldn't open the wave file\n\n") abort(1) end if integer wnd_height wnd_height = (wav_data[WAV_CHANNELS] * TRACK_HEIGHT) + INFO_HEIGHT + TITLE_BAR win = create(Window, "Wave File Display",0,Default,Default, SCREENWIDTH(), wnd_height, 0) for i = 1 to wav_data[WAV_CHANNELS] do track_gfxs = append(track_gfxs, {newGfx(win, 0, (i-1) * TRACK_HEIGHT, SCREENWIDTH(), TRACK_HEIGHT), {}}) end for info_gfx = newGfx(win, 0, TRACK_HEIGHT * wav_data[WAV_CHANNELS], SCREENWIDTH(), INFO_HEIGHT) gfxClear(info_gfx, Black) -- calculate vertical scales and horizontal scale vscale = power(2, wav_data[WAV_BITS]) / TRACK_HEIGHT voffset = floor(power(2, wav_data[WAV_BITS]) / 4) hscale = floor(wav_data[WAV_LEN] / SCREENWIDTH()) -- calculate time scale for info bar -- KISS just mark off seconds, in reality you'd want to let a zoom level to determine this time_s = wav_data[WAV_LEN] / wav_data[WAV_SAMPRATE] -- time in s tscale = SCREENWIDTH() / time_s tick_step = floor(tscale) end_tick = floor(time_s * tick_step) -- last integer time mark -- step through the wav_data[WAV_DATA] to get SCREENWIDTH sample values. -- calculate the difference from the last sample value -- this builds a Shape for each gfx for i = 1 to length(track_gfxs) do lastv = 0 for j = 1 to wav_data[WAV_LEN] by hscale do diff = (lastv - wav_data[WAV_DATA][i][j]) val = floor(diff * vscale) -- next segment is drawn from last position (or start position) to new value -- this is more accurate for a wave form as it can show any DC bias track_gfxs[i][2] = append(track_gfxs[i][2], {1, val, 1}) lastv = wav_data[WAV_DATA][i][j] end for gfxClear(track_gfxs[i][1], gfxColour(BLACK+i)) -- draw the seconds mark for k = 0 to end_tick by tick_step do gfx_draw(track_gfxs[i][1], "line", BrightRed, {k, 0, k, TRACK_HEIGHT}) end for -- draw the center line gfx_draw(track_gfxs[i][1], "line", BrightBlue, {0, voffset, SCREENWIDTH(), voffset}) -- draw the wave form shape (at a starting point with the "shape" method) gfx_draw(track_gfxs[i][1], "shape", BrightWhite, {0, voffset, track_gfxs[i][2]}) -- BUG NOTE: I had real trouble getting this to work until I realised that ------------ The coordinates in the gfx are local to the gfx, so there was ------------ no need to try and relate them to window coordinates as I was ------------ trying to do eg ((i-1)+TRACK_HEIGHT) + voffset :-) end for --trace(1) -- mark the info bar as well label = "seconds" sec = 0 VOID = setGfxFontScale(2) for i = 0 to end_tick by tick_step do gfx_draw(info_gfx, "line", BrightRed, {i, 0, i, 10}) gfxTextOutAt(info_gfx, i + 5, 12, sprintf("%d", {sec}), BrightRed) sec += 1 end for -- scale label gfxTextOutAt(info_gfx, floor(SCREENWIDTH()/2), 24, label, BrightWhite) -- label tracks if wav_data[WAV_CHANNELS] > 2 then for i = 1 to length(track_gfxs) do gfxTextOutAt(track_gfxs[i][1], 10, 20, sprintf("Ch %d", {i}), BrightWhite) end for elsif wav_data[WAV_CHANNELS] = 2 then gfxTextOutAt(track_gfxs[1][1], 10, 20, "L", BrightWhite) -- presumably? gfxTextOutAt(track_gfxs[2][1], 10, 20, "R", BrightWhite) else gfxTextOutAt(track_gfxs[1][1], 10, 20, "Mono", BrightWhite) end if -- doesn't actually do much else include w32start.ew