Author Topic: Write wave files  (Read 1169 times)

Marcus

  • Administrator
  • Hero Member
  • *****
  • Posts: 549
    • View Profile
Write wave files
« on: August 18, 2016 »
Generates three sound effects, saves them as wave and then loads and plays them.

Code: [Select]
' ===============================================================================
' Write an 8 bit, 11025 Hz, wave file from data.
' ===============================================================================


import "Random.lib"

constant:
SAMPLE_RATE 11025

hidden:


' Duration in seconds.
duration = 1

' Data in float format [-1..1]
data#[SAMPLE_RATE*duration]


' Generate explosion sound.
vol# = 1.0
for i = 0 to sizeof(data) - 1
' Noise.
data[i] = (RandomFloat(2.0) - 1.0)*vol
' Fade out.
vol = vol - 1.0/float(sizeof(data))
next
' Write file
_WriteWave "noise.wav", SAMPLE_RATE, data


' Generate beep sound.
a# = 0.0
vol# = 1.0
for i = 0 to sizeof(data) - 1
' Sine.
data[i] = sin(a)*vol
a = a + 16.0
while a > 360.0; a = a - 360.0; wend
' Fade out.
vol = vol - 1.0/float(sizeof(data))
next
' Write file
_WriteWave "sine.wav", SAMPLE_RATE, data


' Generate ... weird sound.
a# = 0.0
b# = 0.0
vol# = 1.0
volIn# = 0.0
for i = 0 to sizeof(data) - 1
' Weird.
data[i] = sin(a)*volIn*vol
a = a + (1.0 + sin(b))*8.0
b = b + 0.5
while a > 360.0; a = a - 360.0; wend
while b > 360.0; b = b - 360.0; wend
' Fade out.
volIn = min#(volIn + 4.0/float(sizeof(data)), 1.0)
vol = vol - 1.0/float(sizeof(data))

next
' Write file
_WriteWave "weird.wav", SAMPLE_RATE, data



' Load the files.
load sound 0, "noise.wav"
load sound 1, "sine.wav"
load sound 2, "weird.wav"

' Play the sound effect when player presses the space bar.
set caret width(primary)/2, 8
center "[1]   Play explosion"
center "[2]   Play beep     "
center "[3]   Play weird    "
center
center "[Esc] Exit          "

do

if keydown("1", true) then play sound 0
if keydown("2", true) then play sound 1
if keydown("3", true) then play sound 2
wait 16

until keydown(27, true)


' ===============================================================================
' Write 8 bit wave file from float array [-1..1].
' ===============================================================================
procedure WriteWave(filename$, rate, &data#[])
rate = rate
create file 0, filename$, true
' Write header.
_WriteBytes 0, "RIFF"
write32 0, 44 + sizeof(data)
_WriteBytes 0, "WAVE"
_WriteBytes 0, "fmt "
write32 0, 0x10
write16 0, 1
write16 0, 1
write32 0, rate
write32 0, rate
write16 0, 1
write16 0, 8
_WriteBytes 0, "data"
write32 0, sizeof(data)
' Write data.
for i = 0 to sizeof(data) - 1
write8 0, 127 + int(data[i]*127.0)
next
free file 0
endproc

' ===============================================================================
' Write string as bytes.
' ===============================================================================
procedure WriteBytes(f, bytes$)
for i = 0 to len(bytes) - 1
write8 f, asc(mid(bytes, i))
next
endproc
« Last Edit: August 18, 2016 by Marcus »
.\\\opz

Marcus

  • Administrator
  • Hero Member
  • *****
  • Posts: 549
    • View Profile
Re: Write wave files
« Reply #1 on: August 18, 2016 »
I'll make a gui, add some curve types, modifiers and post effects (echo, reverb and stuff), and ... well, it'll probably end up as something like SFXR :)
.\\\opz

Rick3137

  • Sr. Member
  • ****
  • Posts: 347
  • May the Force be with You
    • View Profile
    • Rick's Programs
Re: Write wave files
« Reply #2 on: August 18, 2016 »
 That was awesome. Can't wait for the next one.  ;D

Marcus

  • Administrator
  • Hero Member
  • *****
  • Posts: 549
    • View Profile
Re: Write wave files
« Reply #3 on: August 19, 2016 »
Still the same sounds, but I've added some post effects like echo and reverb. It will all make more sense when I've added more modifiers and a GUI with simple sliders for everything.

Code: [Select]
import "Random.lib"

constant:
SAMPLE_RATE 11025

BITS_8  8
BITS_16 16

hidden:


' Duration in seconds.
duration# = 0.75

' Base volume.
baseVolume# = 0.5

' Data in float format [-1..1]
data#[int(float(SAMPLE_RATE)*duration)]


' Generate explosion sound.
vol# = 1.0
for i = 0 to sizeof(data) - 1
' Noise.
data[i] = (RandomFloat(2.0) - 1.0)*baseVolume*vol
' Fade out.
vol = vol - 1.0/float(sizeof(data))
next

data#[] = Smooth(data, 8)
data#[] = Echo(data, 4, 0.5, 0.25)
data#[] = Reverb(data, 0.02, 0.5)


' Write file
_WriteWave "noise.wav", BITS_16, SAMPLE_RATE, data


' Generate beep sound with square/sine mix.
data#[int(float(SAMPLE_RATE)*duration)]
a# = 0.0
vol# = 1.0
' 50% square, 50% sine
square# = 0.5
for i = 0 to sizeof(data) - 1
value# = (1.0 - square)*sin(a)

if sin(a) > 0.0; value = value + square
else; value = value - square
endif

data[i] = value*baseVolume*vol

a = a + 8.0
while a > 360.0; a = a - 360.0; wend
' Fade out.
vol = vol - 1.0/float(sizeof(data))
next

' Write file
_WriteWave "sine.wav", BITS_16, SAMPLE_RATE, data

' Generate ... weird sound.
data#[int(float(SAMPLE_RATE)*duration)]
a# = 0.0
b# = 0.0
vol# = 1.0
volIn# = 0.0
for i = 0 to sizeof(data) - 1
' Weird.
data[i] = sin(a)*baseVolume*volIn*vol
a = a + (1.0 + sin(b))*8.0
b = b + 0.5
while a > 360.0; a = a - 360.0; wend
while b > 360.0; b = b - 360.0; wend
' Fade out.
volIn = min#(volIn + 4.0/float(sizeof(data)), 1.0)
vol = vol - 1.0/float(sizeof(data))
next

data#[] = Echo(data, 2, 0.65, 0.4)
data#[] = Reverb(data, 0.02, 0.5)

' Write file
_WriteWave "weird.wav", BITS_16, SAMPLE_RATE, data



' Load the files.
load sound 0, "noise.wav"
load sound 1, "sine.wav"
load sound 2, "weird.wav"

' Play the sound effect when player presses the space bar.
set caret width(primary)/2, 8
center "[1]   Play explosion"
center "[2]   Play beep     "
center "[3]   Play weird    "
center
center "[Esc] Exit          "

do

if keydown("1", true) then play sound 0
if keydown("2", true) then play sound 1
if keydown("3", true) then play sound 2
wait 16

until keydown(27, true)

' ==============================================================================
' Apply echo effect to data and return as new buffer.
'   count - number of echoes
'   delay - echo delay in seconds
'   drop  - volume drop in percent for each echo
' ==============================================================================
function Echo#[](&data#[], count, delay#, drop#)
delayi = int(delay*float(SAMPLE_RATE))
vol# = 1.0*drop
newData#[sizeof(data) + delayi*count]
for i = 0 to sizeof(data) - 1; newData[i] = data[i]; next
for i = 1 to count
for j = 0 to sizeof(data) - 1
newData[i*delayi + j] = max#(min#(newData[i*delayi + j] + data[j]*vol, 1.0), -1.0)
next
vol = vol*drop
next
return newData
endfunc

function Reverb#[](&data#[], delay#, drop#)
delayi = int(delay*float(SAMPLE_RATE))
newData#[sizeof(data) + delayi]
for i = 0 to sizeof(data) - 1; newData[i] = data[i]; next
for i = 0 to sizeof(data) - 1
newData[i + delayi] = max#(min#(newData[i + delayi] + newData[i]*drop, 1.0), -1.0)
next
return newData
endfunc

function Smooth#[](&data#[], steps)
newData#[sizeof(data)]
mx = sizeof(data) - 1
for i = 0 to sizeof(data) - 1
sum#
c
for j = -steps to steps
sum = sum + data[min(max(i + j, 0), mx)]
ADD c 1
next
newData[i] = sum/float(c)
next
return newData
endfunc


' ===============================================================================
' Write wave file from float data.
'   filename - name of output file (wav)
'   fmt      - BITS_8 or BITS_16
'   rate     - sample rate (11025, 22050 ...)
'   data     - sound data as float array, values in range [-1 .. 1]
' ===============================================================================
procedure WriteWave(filename$, fmt, rate, &data#[])
rate = rate
create file 0, filename$, true
' Write header.
_WriteBytes 0, "RIFF"
if fmt = BITS_8
write32 0, 36 + sizeof(data)
else
write32 0, 36 + sizeof(data)*2
endif
_WriteBytes 0, "WAVE"
_WriteBytes 0, "fmt "
write32 0, 16
write16 0, 1
write16 0, 1
' Sampe rate.
write32 0, rate
' Byte rate.
if fmt = BITS_8
write32 0, rate
else
write32 0, rate*2
endif

if fmt = BITS_8
write16 0, 1
write16 0, 8
else
write16 0, 2
write16 0, 16
endif
_WriteBytes 0, "data"
if fmt = BITS_8
write32 0, sizeof(data)
else
write32 0, sizeof(data)*2
endif
' Write data.
if fmt = BITS_8
for i = 0 to sizeof(data) - 1
write8 0, 127 + int(data[i]*127.0)
next
else
for i = 0 to sizeof(data) - 1
write16 0, int(data[i]*32000.0)
next
endif
free file 0
endproc

' ===============================================================================
' Write string as bytes.
' ===============================================================================
procedure WriteBytes(f, bytes$)
for i = 0 to len(bytes) - 1
write8 f, asc(mid(bytes, i))
next
endproc
« Last Edit: August 19, 2016 by Marcus »
.\\\opz

Rick3137

  • Sr. Member
  • ****
  • Posts: 347
  • May the Force be with You
    • View Profile
    • Rick's Programs
Re: Write wave files
« Reply #4 on: August 19, 2016 »
   Nice effect

   Works good on Windows10, as long as I don't forget to turn off Windows media player.

   (It locks up the sound files.)

Marcus

  • Administrator
  • Hero Member
  • *****
  • Posts: 549
    • View Profile
Re: Write wave files
« Reply #5 on: August 20, 2016 »
It's not finished yet, haven't done the tone and volume vibrato functions yet (not quite sure what I want them to do yet). But here's a version with a GUI that contains lots of sliders:



You can click the 'Load setup' button to load the four settings files (.nfx) located in the nlsfx/sounds folder. Click 'Play sound' to play the loaded sound effect.

You can not compile the sourcecode, since it uses a new function (pow) that I just added (yeah, I only add things when I finally need them myself ...).

There will be several buttons later on for generating random sound effects within some different categories.

.\\\opz

Rick3137

  • Sr. Member
  • ****
  • Posts: 347
  • May the Force be with You
    • View Profile
    • Rick's Programs
Re: Write wave files
« Reply #6 on: August 20, 2016 »
 Looking good. 8)

B+

  • Full Member
  • ***
  • Posts: 215
    • View Profile
Re: Write wave files
« Reply #7 on: August 28, 2016 »
This is really cool! Are these usable yet?

I had perfect aquarium filter noise but couldn't get it to play.

No errors when loading sound file or attempting to play it, no sound either.  :(
B+

Marcus

  • Administrator
  • Hero Member
  • *****
  • Posts: 549
    • View Profile
Re: Write wave files
« Reply #8 on: August 30, 2016 »
This is really cool! Are these usable yet?

I had perfect aquarium filter noise but couldn't get it to play.

No errors when loading sound file or attempting to play it, no sound either.  :(

("nlsfx") + "temp.wav"

How weird :(  I will continue working on it. A temporary WAV file is stored as c:\appdata\nlsfx\temp.wav (appdata is a hidden folder, i think) every time you press the play button (if the sound settings has been changed).
.\\\opz

B+

  • Full Member
  • ***
  • Posts: 215
    • View Profile
Re: Write wave files
« Reply #9 on: August 30, 2016 »
 :o  Yikes! This is more complicated that I thought. I thought this was just going to write a wav file. Geez where did I get that idea  ???

Is this like Naalaa or NNaalaa?  ;)

Well I hope this thing gets working easier or I get it figured out, I want to make noises.  ;D
B+

Marcus

  • Administrator
  • Hero Member
  • *****
  • Posts: 549
    • View Profile
Re: Write wave files
« Reply #10 on: August 31, 2016 »
:o  Yikes! This is more complicated that I thought. I thought this was just going to write a wav file. Geez where did I get that idea  ???

Is this like Naalaa or NNaalaa?  ;)

Well I hope this thing gets working easier or I get it figured out, I want to make noises.  ;D

That was only a test version. Save and Load are for saving/loading configurations, and I didn't add any functionality the Export WAV yet.
.\\\opz

B+

  • Full Member
  • ***
  • Posts: 215
    • View Profile
Re: Write wave files
« Reply #11 on: August 31, 2016 »
:o  Yikes! This is more complicated that I thought. I thought this was just going to write a wav file. Geez where did I get that idea  ???

Is this like Naalaa or NNaalaa?  ;)

Well I hope this thing gets working easier or I get it figured out, I want to make noises.  ;D

That was only a test version. Save and Load are for saving/loading configurations, and I didn't add any functionality the Export WAV yet.

Yeah, I figured as much  ;) being the B that I am, I was trying to be encouraging in a goading sort of way...  :D

I don't know what is out there but you are on to something here.
B+

Rick3137

  • Sr. Member
  • ****
  • Posts: 347
  • May the Force be with You
    • View Profile
    • Rick's Programs
Re: Write wave files
« Reply #12 on: June 20, 2017 »
 Here's my most recent mod of the sound file idea.

 This script makes 44 sound files to use on a keyboard program. Be sure to place in a separate folder before you run it or you will have sound files all over everything. It starts with the key of C4, so it needs to be extended to produce the other 44 keys, to make a full key board.
 It also needs to be calibrated. Someone with a good ear for tones could do it, or someone with a frequency meter could do it. You would then have to adjust the Sample rate variable to the right number.
 
 Adjust the a4 key to 440 cycles per second, and the whole batch should be on key.
« Last Edit: June 20, 2017 by Rick3137 »

Marcus

  • Administrator
  • Hero Member
  • *****
  • Posts: 549
    • View Profile
Re: Write wave files
« Reply #13 on: June 23, 2017 »
Very nice!

I know so little about sound, but it makes one wanna experiment with creating a realistic piano sound :)
.\\\opz