Sound file sample access (WAV or MP3)

General FreeBASIC programming questions.
Sisophon2001
Posts: 1704
Joined: May 27, 2005 6:34
Location: Cambodia, Thailand, Lao, Ireland etc.
Contact:

Sound file sample access (WAV or MP3)

Postby Sisophon2001 » Oct 03, 2019 11:03

Hi,

Is there a convenient library to access individual samples from a sound file? Between WAV and MP3 there are so many sound formats it is discouraging to do from scratch. I had working code years ago, based on code by D.J. Peters, but I have lost it now.

In Python, this is what I want to do, but I don't know Python very well and would prefer to have a WIN-API program in FreeBASIC.

Code: Select all

# Make plots appear inline, set custom plotting style
import matplotlib.pyplot as plt
import numpy as np
from scipy.io import wavfile
from scipy import signal

rate, audio = wavfile.read('out.wav')

audio = np.mean(audio, axis=1)
M = 1024

freqs, times, Sx = signal.spectrogram(audio, fs=rate, window='hanning',
                                      nperseg=M, noverlap=M - 100,
                                      detrend=False, scaling='spectrum')

f, ax = plt.subplots(figsize=(10, 6))
ax.pcolormesh(times, freqs / 1000, 10 * np.log10(Sx), cmap='viridis')
ax.set_ylim([0,20])

ax.set_ylabel('Frequency [kHz]')
ax.set_xlabel('Time [s]')
plt.show()

#######################
import struct
startpos = 6.696
endpos = 7.592
lowfreq = 3
hifreq = 8
startpos = long(startpos * 441)
endpos = long(endpos * 441)
#lowfreq = lowfreq *
#hifreq = hifreq *
# need to learn how to calculate the frequency from 0 to 513.
handle = open('floats.bin', 'wb')
#handle.write(struct.pack('<i', startpos))
handle.write(Sx[:,startpos:endpos].tobytes())
# Write all
#handle.write(Sx[:,:].tobytes())

handle.close()
grindstone
Posts: 721
Joined: May 05, 2015 5:35
Location: Germany

Re: Sound file sample access (WAV or MP3)

Postby grindstone » Oct 03, 2019 16:54

I don't know what exactly you want to do, but here's a snippet that normalizes a single wav - file (pcm or float). It's part of a program I use to batch - normalize / convert the wav - files of a whole directory. For the conversion it uses ffmpeg.

Code: Select all

#Include "..\fbm_RIFFheader.bas"
#Include "vbcompat.bi"

Const As Integer schwarz = 0, blau = 1, gruen = 2, zyan = 3, cyan = 3, rot = 4, magenta = 5, _
                         braun = 6, hellgrau = 7, grau = 8, hellblau = 9, hellgruen = 10, hellzyan = 11, _
                         hellcyan = 11, hellrot = 12, pink = 13, gelb = 14, weiss = 15

Dim As String g
Dim As String quelle, ziel
Dim As Integer laengemerken, keinedatei, header, dateilaenge, subch1, audioformat, kanaele, samplerate, _
               byterate, blockalign, bitspersample, subch2, blocklaenge, x, ma
Dim As LongInt samples, gesamtsamples, bloecke, rest
Dim As Single maxamplitude, dauer, sollwertpcm, sollwertfloat, links, rechts, verst, schwelle
Dim As Double geslinks, gesrechts
Dim As Short Ptr gpp
Dim As Single Ptr gpf

Declare Sub maske
Declare Function vh (x As Single) As Single   
Declare Function db (x As Single) As Single
      
'initialize variables
quelle = "g:\RIFF\RMS Abgleichton.wav" 'source file
ziel = "g:\RIFF\mod.wav" 'destination file

sollwertpcm = -18 'desired value (in dB)
sollwertfloat = -18
schwelle = .2
blocklaenge = 2^25

If quelle = ziel Then 'change file name
   ziel = Left(ziel,InStrRev(ziel,".") - 1) + "_1" + Mid(ziel,InStrRev(ziel,"."))
EndIf

keinedatei = 0
maxamplitude = 0
geslinks = 0
gesrechts = 0
samples = 0
laengemerken = FileLen(quelle)
   
If quelle = "" Then
   End
EndIf

If Open(quelle For Binary Access Read As #1) Then
   Print "File not found"
   Sleep
   End
EndIf

Print #10, quelle;" "; '***
header = 0
Do 'seek 'data'
  header += 1
  Seek #1, header
  g = Input$(4, #1)
Loop Until g = "data"
header += 7
g = Input$(4, #1)
Print

Seek 1,1 'reset file pointer

'determine file parameters
g = Input(4, #1) 'skip the first 4 bytes
dateilaenge = Cvi(Input(4, #1)) 'file length
g = Input(8, #1) 'skip
subch1 = Cvi(Input(4, #1)) 'size of subchunk1
audioformat = CVShort(Input(2, #1)) 'audio format
kanaele = CVShort(Input(2, #1)) 'number of channels
samplerate = Cvi(Input(4, #1))
byterate = Cvi(Input(4, #1))
blockalign = CVShort(Input(2, #1))
bitspersample = CVShort(Input(2, #1))
g = Input(4, #1) 'skip
Seek 1,header - 3
subch2 = Cvi(Input(4, #1))
               
gesamtsamples = (Lof(1)-header)/blockalign 'total number of samples
bloecke = Int(gesamtsamples * blockalign / blocklaenge) 'number of blocks (for input)
rest = gesamtsamples * blockalign - bloecke * blocklaenge

maske

'print title
Locate 1,1
Color weiss,schwarz
Print quelle
      
'print file parameters
Print
Print Tab(17); samplerate; " Hz"
Print Tab(17); bitspersample; " bit ";
Select Case audioformat
   Case 1
      Print"PCM"
   Case 3
      Print "float"
   Case Else
      Color hellrot,schwarz
      Print "*** Unbekanntes Audioformat ***"
      Color weiss,schwarz
      Sleep 2000
      Exit Select
End Select
   
Select Case kanaele
   Case 1
      Print Tab(18); "Mono"
   Case 2
      Print Tab(18); "Stereo"
   Case Else
      Print Tab(17); kanaele
End Select
   
dauer = subch2 / byterate
x = Int(dauer / 60)
g = Str$(dauer - 60 * x)
If InStr(g,".") = 2 Then
   g = "0" + g
EndIf
g = Str$(x) + ":" + g
Print Tab(18); Left$(g,InStr(g,".")+2)
   
'print file names
Print
Print
Print Tab(18); quelle
Print Tab(18); ziel
         
Locate 15,1
Select Case audioformat
   Case 1 'pcm
      Print Tab(18); sollwertpcm; " dB"
   Case 3 'float
      Print Tab(18); sollwertfloat; " dB"
End Select
               
Do
   g = Input(blocklaenge, #1)
   Color weiss,schwarz
                        
   Select Case audioformat 'determine actual value
      Case 1 'pcm
         samples += Len(g)/4   
         For gpp = Cast(Short Ptr,StrPtr(g)) To Cast(Short Ptr,StrPtr(g) + Len(g) - 1) Step 2
            
            'left value
            links = CSng(Abs(*gpp)) / ma 'convert to float and normalize
            If links > maxamplitude Then 'determine peak value
               maxamplitude = links
            EndIf
            geslinks += links * links
            
            'right value
            rechts = CSng(Abs(*(gpp+1))) / ma 'convert to float and normalize
           If rechts > maxamplitude Then 'determine peak value
              maxamplitude = rechts
           EndIf
           gesrechts += rechts * rechts
         Next
                  
      Case 3 'float
         samples += Len(g)/8
         For gpf = Cast(Single Ptr,StrPtr(g)) To Cast(Single Ptr,StrPtr(g) + Len(g) -1) Step 2
            
            'right value
            rechts = Abs(*(gpf+1))
            If rechts > 1 Then
               rechts = 0
            EndIf
            If rechts > maxamplitude Then
              maxamplitude = rechts
           EndIf
           gesrechts += rechts * rechts
          
           'left value
            links = Abs(*gpf)
            If links > 1 Then
               links = 0
            EndIf
            If links > maxamplitude Then
               maxamplitude = links
            EndIf
            geslinks += links * links
         Next
         
   End Select
         
Loop Until Len(g) < blocklaenge

'************************************************************************************
            
'compute amplification
Select Case audioformat
   Case 1 'pcm
      verst = vh(sollwertpcm) / (Sqr((geslinks + gesrechts) / (2*samples))) 
   Case 3 'float
      verst = vh(sollwertfloat) / (Sqr((geslinks + gesrechts) / (2*samples)))
End Select

'print actual value
Locate 16,18,0
Print Int(10 * (db(Sqr(geslinks /samples)))) / 10;" dB"
Locate 17,18,0
Print Int(10 * (db(Sqr(gesrechts/samples)))) / 10;" dB"
Locate 18,18,0
Print Int(10 * (db(Sqr((geslinks + gesrechts) / (2 * samples))))) / 10;" dB"
                  
Close #1
                              
If maxamplitude * verst > 1 Then 'avoid distorsion
   Locate 22,1,0
   Print "Die Verstärkung wurde um ";_
         CInt(Abs(db(maxamplitude * verst))*100)/100;_
         "dB abgesenkt,"
   Print "um eine Übersteuerung zu verhindern"
   verst = verst / (maxamplitude * verst)
EndIf
                              
'print amplification factor
Locate 19,18,0
Print db(verst);" dB"
                  
If Abs(db(verst)) > schwelle Then 'correct volume
   Open quelle For Binary Access Read As #1
   Open ziel For Output As #2
   Print #10, Lof(1);" "; '***
   'transfer header
   Print #2, Input$(header, #1);
   
   'transfer audio samples with new volume
   Do
      g = Input(blocklaenge, #1)
                              
     Select Case audioformat 'compute audio samples
        Case 1 'pcm
           For gpp = Cast(Short Ptr,StrPtr(g)) To Cast(Short Ptr,StrPtr(g) + Len(g) - 1)
               *gpp *= verst
            Next
           Print #2, g;
                         
        Case 3 'float
           For gpf = Cast(Single Ptr,StrPtr(g)) To Cast(Single Ptr,StrPtr(g) + Len(g) - 1)
               *gpf *= verst
            Next
            Print #2, g;
     End Select      
   Loop Until Len(g) < blocklaenge
   
   Close #1
   Close #2
Else 'copy file
   Locate 13,6,0
   Color hellcyan,schwarz
   Print "   kopieren ";
   Color weiss,schwarz
   FileCopy(quelle, ziel)
EndIf

Locate 13,1,0
Print "                "
            
Close
Sleep
         
Sub maske
   
   View Print 1 To 12
   Cls
   View Print 14 To 25
   Cls
   Color hellgrau,schwarz
   View Print
      
  Locate 1,1,0
   Print
   Print
   Print "      Samplerate"
   Print "          Format"
   Print "          Kanäle"
   Print "           Dauer"
   Print
   Print
   Print "Quellverzeichnis"
   Print " Zielverzeichnis"
   Print "           Datei"
   Print
   Print Tab(18); String(50, "°")
   Print
   Print "       Sollpegel"
   Print "     Pegel links"
   Print "    Pegel rechts"
   Print "     Gesamtpegel"
   Print "     Verstärkung"
      
End Sub

Function vh (x As Single) As Single 'rechnet dB in verhältnis um
   
   Return Exp((x / 20) * Log(10))
   
End Function

Function db (x As Single) As Single 'rechnet verhältnis in dB um
   
   Return 20*(Log(x)/Log(10))
   
End Function
badidea
Posts: 2057
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Sound file sample access (WAV or MP3)

Postby badidea » Oct 03, 2019 22:37

I would say: 2 steps.
1. Read the files (of different formats) into memory in to a standard format. This is what sound libraries do as the output device (the thing that produces actual sound waves) expects a certain format. Or several formats (mono/stereo, 8 bit/16-bit), but at least a relative simple array [note1]. fbSound supports several formats, including wave and mp3.
2. Instead for playing the array of samples, process the array with your spectogram tool.

I just posted something similar here (just plotting the samples, no FFT): viewtopic.php?f=17&t=26256&p=264766#p264766 This library however does not support mp3.

[note1] For 2 channels (stereo), the left and right channel are interleaved. For your program probably not wanted. You might want to convert in to 2 separate arrays (left & right), or to 1 'mono' array (average/sum of left and right). Maybe also to floating point (with value -1...+1).
Sisophon2001
Posts: 1704
Joined: May 27, 2005 6:34
Location: Cambodia, Thailand, Lao, Ireland etc.
Contact:

Re: Sound file sample access (WAV or MP3)

Postby Sisophon2001 » Oct 04, 2019 4:23

Thanks to both badidea and grindstone for your help. I will study the examples you shared.
Gromow
Posts: 9
Joined: May 03, 2019 14:55

Re: Sound file sample access (WAV or MP3)

Postby Gromow » Oct 14, 2019 7:36

My friend advised me this service the online file converter https://onlineconvertfree.com/ and I was with satisfied.
srvaldez
Posts: 2429
Joined: Sep 25, 2005 21:54

Re: Sound file sample access (WAV or MP3)

Postby srvaldez » Oct 14, 2019 14:22

@Gromow
I would like to know whether you are a human or a BOT, we had several BOT posting lately and your posts look suspicious
Gromow
Posts: 9
Joined: May 03, 2019 14:55

Re: Sound file sample access (WAV or MP3)

Postby Gromow » Oct 15, 2019 22:37

srvaldez wrote:@Gromow
I would like to know whether you are a human or a BOT, we had several BOT posting lately and your posts look suspicious

I'm a human.

Return to “General”

Who is online

Users browsing this forum: No registered users and 7 guests