Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Any C programmers wanna help convert code to convert between MIDI + CSV?
#84
Yo, @madscijr ... Does this help you with your WAV file stuff?

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.
Tread on those who tread on you

Reply


Messages In This Thread
RE: Any C programmers wanna help convert code to convert between MIDI + CSV? - by SpriggsySpriggs - 09-12-2022, 02:00 PM



Users browsing this thread: 18 Guest(s)