[Delphi] Wav files icm TChart

Pagina: 1
Acties:

  • Kogelvis
  • Registratie: Maart 2001
  • Laatst online: 28-04 16:21

Kogelvis

Nu ook met gitaar

Topicstarter
Hoi,

Ik en nog iemand zijn hier bezig om Wav files in een TChart te krijgen met Delphi 7.

De header uitlezen is al prima gegaan met behulp van een Filestream en read().
Dan komen we aan bij het data block met de sounddata.
volgens http://ccrma-www.stanford.../422/projects/WaveFormat/
begint het datablock bij byteoffset 44.
Ook vertelt dit document dat sample's uit 4 bytes bestaan, de eerste 2 bytes zijn sounddata voor het linkerkanaal en de laatste 2 bytes van de sample zijn voor het rechterkanaal.

Wat wij als volgt doen is weer een filestream openen en deze starten op positie 44 dan laten we hem in een while loop lopen tot hij bij het einde van de file komt.
Zolang hij bezig is leest hij een byte uit stopt het in een integer en leest nog een byte uit en stopt het weer in een integer, deze 2 getallen worden bij elkaar opgetelt en vervolgens toegevoegd aan de tchartserie.
Vervolgens loopt hij dit stappenplan nog een keer door voor het rechterkanaal en begint dan weer overnieuw.

De code:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
FileStream := TFileStream.Create(WavOpenDialog.FileName, fmOpenRead);
try
    FileStream.Position := 44;
    while FileStream.Position < FullFileSize do
    begin
       FileStream.Read(leftTemp1,1);
       FileStream.Read(leftTemp2,1);
       left := leftTemp1 + leftTemp2;
       Series1.Add(left,'',clBlue);
       FileStream.Read(rightTemp1,1);
       FileStream.Read(rightTemp2,1);
       right := rightTemp1 + rightTemp2;
       right := (right - 2 * right);
       Series1.Add(right,'',clRed);
    end;
  finally
    FileStream.Free;
end;


Tot zover ondervinden wij geen problemen en bij het runnen van het programma krijgen we ook keurig een grafiek.

Als wijze van test gebruiken wij de ringout.wav in de windows media directory.

Deze file ingelezen in het eigen programma met blauw voor het linkerkanaal en rood voor het rechterkanaal, eronder groen voor het inlezen met adobe audition (vroeger cooledit pro) zoals men kan zien komen deze 2 niet echt overeen.

Afbeeldingslocatie: http://webserv.nhl.nl/~helli200/wwav.jpg

heeft iemand enig idee wat hier aan te doen is om deze 2 grafieken min of meer gelijk te trekken? hierover is bij ome google en de search zeer weinig te vinden.

Bijvoorbaat dank.

<Jeroen> Wirf: vrouwen versieren kan je gewoon in het OSI model proppen hoor :P
I am dyslexic of Borg prepare to have your ass laminated
Real Programmers always confuse Christmas and Halloween because oct31 = dec25


  • -=bas=-
  • Registratie: Oktober 2000
  • Laatst online: 22-04-2025
Het lijkt wel of je een histogram gebruikt om de wav-data te tonen?
De ene waarde zit altijd op de vertikale as.

Kan je niet beter een TLineSeries, TFastLineSeries of TChartShape gebruiken om je data weer te geven?

Senile! Senile Oekaki


  • Kogelvis
  • Registratie: Maart 2001
  • Laatst online: 28-04 16:21

Kogelvis

Nu ook met gitaar

Topicstarter
Binnen de tchart gebruiken wij een TBarseries om dit in te zetten.

<Jeroen> Wirf: vrouwen versieren kan je gewoon in het OSI model proppen hoor :P
I am dyslexic of Borg prepare to have your ass laminated
Real Programmers always confuse Christmas and Halloween because oct31 = dec25


  • Kogelvis
  • Registratie: Maart 2001
  • Laatst online: 28-04 16:21

Kogelvis

Nu ook met gitaar

Topicstarter
Ok na nog wat verder prutsen hebben we de oplossing gevonden we hebben nu inderdaad een fastline serie gepakt en we waren nog een klein beetje fout bezig met de bitspersample want als deze 8 is word dit in een byte opgeslagen maar als deze 16 is in een smallint en wij propten het telkens in een integer.

nog even de code voor de geinterreseerden:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
FileStream := TFileStream.Create(WavOpenDialog.FileName, fmOpenRead);
try
   FileStream.Position := 44;
   if WaveHeader.BitsPerSample = 16 then
   begin
      while FileStream.Position < FullFileSize do
      begin
         FileStream.Read(Sleft,2);
         Series2.Add(Sleft,'',clRed);
         FileStream.Read(Sright,2);
         Series2.Add(Sright,'',clRed);
      end;
   end else if WaveHeader.BitsPerSample = 8 then
   begin
      while FileStream.Position < FullFileSize do
      begin
         FileStream.Read(Uleft,1);
         Series2.Add(Uleft,'',clBlue);
         FileStream.Read(Uright,1);
         Uright := (Uright - 2 * Uright);
         Series2.Add(Uright,'',clRed);
      end;
   end;
 finally
   FileStream.Free;
end;


verder nog bedankt voor de hulp. _/-\o_

<Jeroen> Wirf: vrouwen versieren kan je gewoon in het OSI model proppen hoor :P
I am dyslexic of Borg prepare to have your ass laminated
Real Programmers always confuse Christmas and Halloween because oct31 = dec25


Verwijderd

Gaat dit niet heel erg lang duren? (een read per sample EN een series.add per sample).
Het gaat veel sneller als een tijdelijke array (van een paar duizend elementen) gebruikt wordt en de series.addarray

  • Kogelvis
  • Registratie: Maart 2001
  • Laatst online: 28-04 16:21

Kogelvis

Nu ook met gitaar

Topicstarter
thnx for the tip,

dat ga ik zeker eens testen.

edit:

kan iemand mij vertellen hoe ik een (dynamische) array van smallint werkend krijg met de addarray functie van die series die alleen maar array's van double accepteerd?

[ Voor 65% gewijzigd door Kogelvis op 11-12-2003 18:15 ]

<Jeroen> Wirf: vrouwen versieren kan je gewoon in het OSI model proppen hoor :P
I am dyslexic of Borg prepare to have your ass laminated
Real Programmers always confuse Christmas and Halloween because oct31 = dec25


Verwijderd

Kogelvis schreef op 11 december 2003 @ 17:45:
thnx for the tip,

dat ga ik zeker eens testen.

edit:

kan iemand mij vertellen hoe ik een (dynamische) array van smallint werkend krijg met de addarray functie van die series die alleen maar array's van double accepteerd?
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Var 
  IntArr: Array of SmallInt;
  DblArr: Array of Double;
begin
  .......
  filestream.read(intArr[0],len);
  for i:=0 to (len div 2)-1 do begin
    DblArr[i]:=intArr[i*2];
  end;
  Series.AddArray(DblArr);
  for i:=0 to (len div 2)-1 do begin
    DblArr[i]:=intArr[i*2+1];
  end;
  Series.AddArray(DblArr);
  .........
end;

[ Voor 4% gewijzigd door Verwijderd op 12-12-2003 17:38 ]


  • Kogelvis
  • Registratie: Maart 2001
  • Laatst online: 28-04 16:21

Kogelvis

Nu ook met gitaar

Topicstarter
Ten eerste hartelijk bedankt voor dat stukje codevoorbeeld echter vraag ik me nog 1 ding af:
Bij alle wavfiles die ik inlees komt op de manier die ik zelf had aan het eind telkens een hele grote piek voor dit heb ik opgelost door even 48 byte minder in te lezen met de read, hierdoor kwam de grafiek stukken beter op mijn scherm.
Echter nu met het codevoorbeeld van PtDw wat ik op meerdere manieren heb aangepast krijg ik nu op de helft van mn grafiek die ontzettend hoge piek en dan de andere helft Flatline enig idee hoe dit kan?

<Jeroen> Wirf: vrouwen versieren kan je gewoon in het OSI model proppen hoor :P
I am dyslexic of Borg prepare to have your ass laminated
Real Programmers always confuse Christmas and Halloween because oct31 = dec25


Verwijderd

My bad.

je moet len*SizeOf(SmallInt) (=len*2) bytes lezen om de len-elementen-lange temporary array te vullen. De DblArr moet de helft van de lengte van de IntArr hebben, omdat er 2kanalen gebruikt worden.
Gebruik je trouwens de lengte van de wav uit de header of gewoon de bestandslengte? Want achter de wav-informatie kan soms wat copyrigt/ extra info staan, wat als geconverteerd naar smallints grote waarden kan geven.
Als je serieuzere (lange) wav's wil openen moet je je wel realiseren dat de charts erg veel geheugen kunnen gaan gebruiken (+/- 2*20 bytes/sample ??) ipv. 4 in het bestand

  • Kogelvis
  • Registratie: Maart 2001
  • Laatst online: 28-04 16:21

Kogelvis

Nu ook met gitaar

Topicstarter
ik zal het nog eens proberen en die copyright information daar zeg je wat vandaar kan die piek er wel eens zijn dan ga ik die lengte uit de header wel gebruiken :D enne wat zou je adviseren ipv een tchart als ik toch met wat snelheid langere wav files wil openen?

<Jeroen> Wirf: vrouwen versieren kan je gewoon in het OSI model proppen hoor :P
I am dyslexic of Borg prepare to have your ass laminated
Real Programmers always confuse Christmas and Halloween because oct31 = dec25


Verwijderd

Voor langere wav's: gebruik een fastlineseries, en teken zo min mogelijk punten. Laat punten weg als je helemaal uitgezoemd hebt, en teken alleen de punten die kan zien als je ingezoemd hebt. Als je dat goed doet hou je ongeveer de breedte in pixels op het scherm over aan punten. Als je het verschil niet wil zien moet je per punt het (abs)maximum berekenen van de weggelaten punten en van het maximum naar het minimum tekenen.
Teken de signalen opnieuw na TChart.Onscroll/TChart.OnZoom en onUndoZoom
met addXY, wat jammergenoeg weer alleen per punt werkt. Dan moet je ook nog beslissen of je de wav tijdelijk in het geheugen opslaat (sneller +eenvoudiger als het in het fys. geh. past) of iedere keer van de HD-leest.

  • -=bas=-
  • Registratie: Oktober 2000
  • Laatst online: 22-04-2025
Los het inderdaad op zoals bij Soundforge.
hierbij is als het ware de data en de view van de data losgekoppeld.
Afhankelijk van een aantal zaken bepaal je wat er getoond moet worden.
Hierme voorkom je dat je objecten krijgt die enorm veel geheugen en resources slurpen. :)

Senile! Senile Oekaki


  • Kogelvis
  • Registratie: Maart 2001
  • Laatst online: 28-04 16:21

Kogelvis

Nu ook met gitaar

Topicstarter
Bedankt voor de tips ik zal dat eens proberen uit te voeren,
het lijkt me nl. niet iets wat ik als beginnende programmeur even 123 uitvoer maar de vakantie ligt al binnen zichtbereik :D

<Jeroen> Wirf: vrouwen versieren kan je gewoon in het OSI model proppen hoor :P
I am dyslexic of Borg prepare to have your ass laminated
Real Programmers always confuse Christmas and Halloween because oct31 = dec25

Pagina: 1