09-12-2022, 02:00 PM
(This post was last modified: 09-12-2022, 05:26 PM by SpriggsySpriggs.)
Yo, @madscijr ... Does this help you with your WAV file stuff?
This version is a direct C translation:
And because I know you like to have things done with QB64 code, here is a version that produces the exact same file but uses only built-in functions:
P.S. I personally dislike the naming scheme and case used in the original code but chose to use the same style and names so that it would be easier for you to see the relation. I typically prefer Pascal case for everything that isn't a TYPE or CONSTANT declaration.
P.P.S I know that both code blocks produce the exact same file by doing a comparison in Notepad++. Also, both files play just fine in Windows. Had some issues at first with using strictly QB64 functions as I forgot that we use base 1 while C uses base 0.
This version is a direct C translation:
Code: (Select All)
Option Explicit
$NoPrefix
$Console:Only
Const WAVFILE_SAMPLES_PER_SECOND = 44100
Const SEEK_SET = 0
Type WAVFILE_HEADER
As String * 4 riff_tag
As Long riff_length
As String * 4 wave_tag, fmt_tag
As Long fmt_length
As Integer audio_format, num_channels
As Long sample_rate, byte_rate
As Integer block_align, bits_per_sample
As String * 4 data_tag
As Long data_length
End Type
Declare CustomType Library
Function fopen%& (filename As String, mode As String)
Sub fwrite (ByVal buffer As Offset, Byval size As Offset, Byval count As Offset, Byval stream As Offset)
Sub fflush (ByVal stream As Offset)
Function ftell& (ByVal stream As Offset)
Sub fseek (ByVal stream As Offset, Byval offset As Long, Byval origin As Long)
Sub fclose (ByVal stream As Offset)
End Declare
Const NUM_SAMPLES = WAVFILE_SAMPLES_PER_SECOND * 2
Dim As Integer waveform(0 To NUM_SAMPLES - 1)
Dim As Double frequency: frequency = 440.0
Dim As Long volume: volume = 32000
Dim As Long i
For i = 0 To NUM_SAMPLES - 1
Dim As Double t: t = i / WAVFILE_SAMPLES_PER_SECOND
waveform(i) = volume * Sin(frequency * t * 2 * Pi)
Next
Dim As Offset f: f = wavfile_open("sound.wav")
wavfile_write f, waveform(), NUM_SAMPLES
wavfile_close f
Function wavfile_open%& (filename As String)
Dim As WAVFILE_HEADER header
Dim As Long samples_per_second: samples_per_second = WAVFILE_SAMPLES_PER_SECOND
Dim As Long bits_per_sample: bits_per_sample = 16
header.riff_tag = "RIFF"
header.wave_tag = "WAVE"
header.fmt_tag = "fmt "
header.data_tag = "data"
header.riff_length = 0
header.fmt_length = 16
header.audio_format = 1
header.num_channels = 1
header.sample_rate = samples_per_second
header.byte_rate = samples_per_second * (bits_per_sample / 8)
header.block_align = bits_per_sample / 8
header.bits_per_sample = bits_per_sample
header.data_length = 0
Dim As Offset file: file = fopen(filename + Chr$(0), "wb+" + Chr$(0))
If file = 0 Then Exit Function
fwrite Offset(header), Len(header), 1, file
fflush file
wavfile_open = file
End Function
Sub wavfile_write (file As Offset, wav_data() As Integer, length As Long)
fwrite Offset(wav_data()), 2, length, file
End Sub
Sub wavfile_close (file As Offset)
Dim As Long file_length: file_length = ftell(file)
Dim As WAVFILE_HEADER header
Dim As Long data_length: data_length = file_length - Len(header)
fseek file, Len(header) - 4, SEEK_SET
fwrite Offset(data_length), Len(data_length), 1, file
Dim As Long riff_length: riff_length = file_length - 8
fseek file, 4, SEEK_SET
fwrite Offset(riff_length), Len(riff_length), 1, file
fclose file
End Sub
And because I know you like to have things done with QB64 code, here is a version that produces the exact same file but uses only built-in functions:
Code: (Select All)
Option Explicit
$NoPrefix
$Console:Only
Const WAVFILE_SAMPLES_PER_SECOND = 44100
Type WAVFILE_HEADER
As String * 4 riff_tag
As Long riff_length
As String * 4 wave_tag, fmt_tag
As Long fmt_length
As Integer audio_format, num_channels
As Long sample_rate, byte_rate
As Integer block_align, bits_per_sample
As String * 4 data_tag
As Long data_length
End Type
Const NUM_SAMPLES = WAVFILE_SAMPLES_PER_SECOND * 2
Dim As Integer waveform(0 To NUM_SAMPLES - 1)
Dim As Double frequency: frequency = 440.0
Dim As Long volume: volume = 32000
Dim As Long i
For i = 0 To NUM_SAMPLES - 1
Dim As Double t: t = i / WAVFILE_SAMPLES_PER_SECOND
waveform(i) = volume * Sin(frequency * t * 2 * Pi)
Next
Dim As Long f: f = wavfile_open("sound.wav")
wavfile_write f, waveform()
wavfile_close f
Function wavfile_open& (filename As String)
Dim As WAVFILE_HEADER header
Dim As Long samples_per_second: samples_per_second = WAVFILE_SAMPLES_PER_SECOND
Dim As Long bits_per_sample: bits_per_sample = 16
header.riff_tag = "RIFF"
header.wave_tag = "WAVE"
header.fmt_tag = "fmt "
header.data_tag = "data"
header.riff_length = 0
header.fmt_length = 16
header.audio_format = 1
header.num_channels = 1
header.sample_rate = samples_per_second
header.byte_rate = samples_per_second * (bits_per_sample / 8)
header.block_align = bits_per_sample / 8
header.bits_per_sample = bits_per_sample
header.data_length = 0
If FileExists(filename) Then Kill filename
Dim As Long file: file = FreeFile
Open "B", file, filename
Put file, , header
wavfile_open = file
End Function
Sub wavfile_write (file As Long, wav_data() As Integer)
Put file, , wav_data()
End Sub
Sub wavfile_close (file As Long)
Dim As Long file_length: file_length = LOF(file)
Dim As WAVFILE_HEADER header
Dim As Long data_length: data_length = file_length - Len(header)
Put file, Len(header) - 3, data_length
Dim As Long riff_length: riff_length = file_length - 8
Put file, 5, riff_length
Close file
End Sub
P.S. I personally dislike the naming scheme and case used in the original code but chose to use the same style and names so that it would be easier for you to see the relation. I typically prefer Pascal case for everything that isn't a TYPE or CONSTANT declaration.
P.P.S I know that both code blocks produce the exact same file by doing a comparison in Notepad++. Also, both files play just fine in Windows. Had some issues at first with using strictly QB64 functions as I forgot that we use base 1 while C uses base 0.
Ask me about Windows API and maybe some Linux stuff