Hallo,
Ik had een heel tijdje geleden een ecg circuit gebouwd en registreerde het signaal toen zoals ik hier (http://www.circuitsonline.net/forum/view/114059/2) toen gezegd had (een ADC rechtstreeks uitlezen met de LPT-poort). Dit was geen ideale manier, maar het werkte wel en toen had ik al een programma gemaakt om het volledige 12 leads ecg op een blad te zetten en de hartslag, QRS-duur,.. te meten.
Nu heb ik mijn ecg schema aangesloten op mijn geluidskaard en het signaal opgenomen met audacity. Ik heb gemerkt dat het signaal wonderbaarlijk veel beter van kwaliteit wordt wanneer ik een low pass filter van 40 Hz gebruik.
Nu zou ik graag de wav-bestanden die ik opneem gebruiken in mijn programma dat ik al gemaakt had. Mijn programma had ik in visual basic gemaakt en hier sloeg ik de gegevens op in 2 array variabelen: één voor de tijd en één voor de amplitude:
Dim Itijd() As Single
Dim Ispanning() As Single
Nu zou ik in deze variabelen graag de waarden zetten die afkomstig zijn uit een wav-bestand.
Mijn vraag is dus eigenlijk:
Hoe kan ik in visual basic uit een wav-bestand de tijd en amplitude van elk meetpunt verkrijgen?
Met dank bij voorbaat,
Tom Bleeser
De structuur van een .wav-file kun je overal vinden; bijvoorbeeld hier:
https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
Het tijdstip behorende bij een sample staat niet in de file. Maar omdat je het aantal samples per seconde weet, kun je dat tijdstip zelf uitrekenen.
Bedankt!
Ik lees de bestanden nu uit met
Dim Byt1() As Byte = IO.File.ReadAllBytes("c:\temp\ecg.wav")
Het lukt mij nu om bestanden met 8 bits per sample uit te lezen: deze hebben gewoon losse bytes van 0 tot 255 met 128 als nulpunt.
Bij bestanden met 16 bits per sample doe ik hetvolgende, maar dan bekom ik geen goede grafiek:
bytenummer 44 45 46 47 48 49 50 51
decimale uitlezing 117 2 218 1 70 2 27 2
hexadecimaal omgezet 75 2 DA 1 46 2 1B 2
samengevoegd hexa 275 1DA 246 21B
decimaal samen 629 474 582 539
Als ik een grafiek maak met de gegevens uit de laatste regel klopt dit niet.
Wat doe ik verkeerd?
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
maartenbakker
Golden Member
www.elba-elektro.nl | "The mind is a funny thing. Sometimes it needs a good whack on the side of the head to jar things loose."
Ik kan het nu even niet zo snel narekenen, maar het eerste dat in me opkwam: big-endian versus little-endian.
Niet helemaal 'RAW' natuurlijk; er zit immers een RIFF header voor. Maar die sloop je er af, dat ging bij de 8-bits data ook goed.
Je probeert niet toevallig een stereo-file uit te lezen? Dan is het steeds twee bytes links, dan twee bytes rechts, dan weer links, et cetera.
Als je een mono signaal als stereo opslaat, kan het zijn dat het 'andere' kanaal allemaal nullen bevat, maar sommige programma's schrijven dan gewoon L en R hetzelfde, zodat je alles twee keer ziet.
De oplossing is in beide gevallen hetzelfde: steeds twee overslaan. 
Mocht je inderdaad een RIFX inplaats van een RIFF hebben, dan moet je lo en hi even omdraaien. Dus niet a + 256*b, maar 256*a + b.
e: Je weet toch dat de 16-bits data 2's complement is, hè? Alles wat meer dan 32767 lijkt, is eigenlijk negatief. Zo:
32768 -32768
32769 -32767
... ...
65534 -2
65535 -1
0 0
1 1
... ...
32766 32766
32767 32767
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Net even geprobeerd met stereo testbestandje. Met een haastig geschreven basic programmaatje kan ik de twee golfjes plotten.
Het werkt zoals in de beschrijving: 44 bytes header, dan steeds twee bytes links, twee bytes rechts, enzovoorts; steeds eerst lo, dan hi; 2's complement.
Bedankt, ik had een mono-bestand, dus dat was niet het probleem, maar wel de 2's complement waar ik geen rekening mee gehouden had.
Ik heb het aangepast en nu heb ik al een grafiek die er op lijkt, maar nu staan er soms punten in de buurt van 0 die er niet horen te staan.
Hoe zou dat komen?
Mijn grafieken zien er nu zo uit:
https://www.dropbox.com/s/1wks80brolj7sir/Klembord01.jpg
https://www.dropbox.com/s/fz0oliudrqtu4sh/Klembord02.jpg
(bovenaan grafiek zoals in audacity, onderaan die van in mijn programma)
Hoe zou ik die horizontale puntenlijn weg kunnen krijgen?
Nu gebruik ik volgende code:
(De array Byt1 bevat de bytes uit het wav bestand)
For teller = 0 To aantalsamples * 2 - 1
tijd(teller / 2) = (teller / 2) * (1 / samplefreq)
samengezetdecimaal = (Convert.ToInt32(Hex(Byt1(teller + 45)) & Hex(Byt1(teller + 44)), 16))
If samengezetdecimaal > 32767 Then
spanning(teller / 2) = -(65536 - samengezetdecimaal)
Else
spanning(teller / 2) = samengezetdecimaal
End If
teller = teller + 1
Next
[Bericht gewijzigd door Henry S. op (58%)]
Gebruik je wel integers? Want dit lijkt op afrondfouten. Bovendien lijkt mij de berekening van een 16-bits getal uit twee unsigned decimals een beetje omslachtig, waarom niet gewoon
C = a * 256 + b ?
Arabel
Re-integratiecoach uitgerangeerde en degoutante electronen
Hoe zou ik die horizontale puntenlijn weg kunnen krijgen?
Lijkt op Buffer over/under runs .. een bekend fenomeen als de buffersize niet klopt.
Beetje opschonen, alle keer 2, /2 kan weg en breuk omdraaien voor foutcorrectie!
De teller ophogen binnen de for lus is not done, gebruik dan op zijn minst de 'step' parameter van for (juck!)
Is er trouwens niet gewoon een functie (call, whatever, ken de taal niet) waarbij je in één keer een signed integer inleest uit de file?
Progger
GMT+1
het probleem zit hem hier:
Hex(Byt1(teller + 44)Ik denk dat Byt1 je data uit de file is. door er een hexadecimaal getal van te maken, kun je deze inderdaad samenvoegen.
die spikes komen doordat je de binaire waarde omzet naar een ascii string, die concat en dan terugconvert naar int. de functie hex geeft meestal 2 karakters, maar niet altijd.
http://msdn.microsoft.com/en-us/library/963zt96e(v=vs.90).aspx
Dim TestHex As String
' Returns 5.
TestHex = Hex(5)
' Returns A.
TestHex = Hex(10)
' Returns 1CB.
TestHex = Hex(459)de beste methode is natuurlijk die van Rob:
Op 3 februari 2014 09:11:53 schreef RobvdVeer:
C = a * 256 + b ?
http://msdn.microsoft.com/en-us/library/zew1e4wc(v=vs.90).aspx
door de ASC functie te gebruiken kun je binaire waarde van de byte als getal gebruiken. daarna kun je die vermenigvuldigen (eigenlijk 8 plaatsen shiften) en optellen.
in jouw geval krijg je bijv voor de 2 samplewaarden 19215 en 19216
19215=4B0F (opgeslagen als 15,75)
19216=4B10 (opgeslagen als 16,75)
samengezetdecimaal = (Convert.ToInt32(hex(75)&hex(15), 16))
samengezetdecimaal = (Convert.ToInt32(hex(75)&hex(16), 16))
wordt:
samengezetdecimaal = (Convert.ToInt32("4B"&"F", 16))
samengezetdecimaal = (Convert.ToInt32("4B"&"10", 16))
4BA =1215
4B10=19216Progger
GMT+1
het probleem is niet de voorloopnul, dat is het gevolg van de verkeerde methode.
natuurlijk is het makkelijk om bytes als hexadecimale karakters te concatten, maar het is veel beter om de bytes te shiften en als getallen te behandelen.
Bedankt!!!
Nu werkt het!
Ik heb het nu zo gedaan:
For teller = 0 To aantalsamples * 2 - 2
tijd(teller / 2) = (teller / 2) * (1 / samplefreq)
samengezetdecimaal = Byt1(teller + 45) * 256 + Byt1(teller + 44)
If samengezetdecimaal > 32767 Then
spanning(teller / 2) = -(65536 - samengezetdecimaal)
Else
spanning(teller / 2) = samengezetdecimaal
End If
teller = teller + 1
Next
Op 3 februari 2014 20:13:55 schreef Progger:
het probleem is niet de voorloopnul, dat is het gevolg van de verkeerde methode.natuurlijk is het makkelijk om bytes als hexadecimale karakters te concatten, maar het is veel beter om de bytes te shiften en als getallen te behandelen.
Er is een verschil tussen foute code, en code die beter kan. De voorloopnul missen is een fout met incorrect resultaat tot gevolg, de *256 is een "verbetering" (improvement).
Overigens vind ik "bytes als hex (...) concatten" persoonlijk niet vallen onder de categorie 'eenvoudig', maar dat is mijn persoonlijke mening. Fout is fout, en goed kan beter, maar is nooit fout.