Springen naar inhoud

[c] wav-bestand manipuleren


  • Log in om te kunnen reageren

#1

rvdp

    rvdp


  • >25 berichten
  • 43 berichten
  • Gebruiker

Geplaatst op 12 april 2008 - 09:18

Ik heb volgende opdracht gekregen in C, waar ik weinig tot geen ervaring in heb.

# Project: inlezen en bewerken van een .wav bestand in C

* Opgave: Schrijf een applicatie in C die
o een WAV bestand inleest (test file)
o de volgende informatie over dit bestand kan afdrukken naar de standaard uitvoer:
+ de naam van de applicatie (gebruik hier voor de eigenschappen van argv), informatie over de auteur en hulp over het gebruik
+ alle gegevens die in de header chunk staan. Een wav bestand bestaat uit een header en data chunk. De header chunk bevat metadata over de wav file (bijv. lengte, samplerate, mono of stereo, enz...) en de data chunk bevat de eigenlijke data
+ een waarschuwing indien uw applicatie niet in staat is de data chunk van het wav bestand te interpreteren (bvb doordat uw applicatie de gebruikte encodering niet ondersteunt)
o een nieuw bestand wegschrijft dat de volgende aanpassingen kan bevatten:
+ aangepaste samplerate (dit betekent de meta data uit de header chunk aanpassen): hierdoor zal het resultaat sterk vervormd klinken (waarom?)
+ decimatie: verlagen van de samplerate met een bepaalde factor waarbij je ervoor zorgt dat je voor de nieuwe sample periode slechts 1 sample per periode krijgt (door samples te elimineren) en de nieuwe samples nog steeds op dezelfde tijdstippen afgespeeld worden (neem voor deze factor een macht van 2) (dit betekent zowel de meta data in de header als de data in de data chunk aanpassen)
+ aanpassen van het volume: vermenigvuldig alle samples met een constante waarde (waarschuwing: pas op voor overflow!)
+ echo-effect: tel bij elke sample op tijdstip t de waarde van de sample op tijdstip t-delay op, let erop dat er geen clipping optreedt ! Neem hiervoor uw voorzorgen (zie vorige mogelijkheid)
+ fading: zorg ervoor dat het geluidsfragment gedempt begint (samplewaarde * factor << 1), en de samples na een bepaalde tijd hun originele waarde terugkrijgen
+ conversie mono <-> stereo (Header en Data chunk aanpassen)
+ clipping detectie: rapporteer de samples waarvan de waarde gelijk is aan de maximale waarde die met de gebruikte woordlengte bereikt kan worden; hoe meer opeenvolgende samples deze waarde hebben, hoe erger het clipping effect is. Past dit eventueel toe op wav files van bestaande cd's.
+ maximale versterking zonder clipping: vermenigvuldig alle samples met een constante waarde zodat de sample met de grootste waarde de grootste waarde heeft dat in de gebruikte woordlengte past (Data chunck aanpassen)


Het gaat om het aanpassen van dit programma:


[codebox]#include <stdio.h>
#include <stdlib.h>
#include <string.h>


typedef struct wav_header{
char riff[4]; /* "RIFF" (4 bytes) */
long TotLen; /* File length - 8 bytes (4 bytes) */
char wavefmt[8]; /* "WAVEfmt " (8 bytes) */
long Len; /* Remaining length (4 bytes) */
short format_tag; /* Tag (1 = PCM) (2 bytes) */
short channels; /* Mono=1 Stereo=2 (2 bytes) */
long SamplesPerSec; /* No samples/sec (4 bytes) */
long AvgBytesPerSec; /* Average bytes/sec (4 bytes) */
short BlockAlign; /* Block align (2 bytes) */
short FormatSpecific; /* 8 or 16 bit (2 bytes) */
char data[4]; /* "data" (4 bytes) */
long datalen; /* Raw data length (4 bytes) */
/* ..data follows. Total header size = 44 bytes */

} wav_header_s;


int main(void)
{
wav_header_s header;
FILE *in_fp, *out_fp;
char in_file[40], out_file[40];
short *audiodat;
int filelength, wavlength, datalength;

strcpy(in_file,"test.wav");
if ((in_fp = fopen(in_file, "rb")) == NULL)
{
printf("'%s' is niet te openen.\n", in_file);
exit(0);
}

fread(&header, 44, 1, in_fp); /* Lees wav header */

filelength = header.TotLen; /* Stop de lengte van het bestand uit de struct */
wavlength = header.datalen; /* Lees de lengte van de data uit de struct */
datalength = wavlength/2; /* Het aantal samples: in dit voorbeeld zijn er 2 kanelen: stereo !! */

printf("Lengte bestand = %d bytes\n", filelength);
printf("Aantal kanalen = %d channels\n", header.channels);
printf("Datalengte = %d bytes\n", wavlength);
printf("Samples per seconde = %ld bytes\n", header.SamplesPerSec);
printf("Aantal samples = %d\n", datalength);
printf("Formaat = %d\n", header.FormatSpecific);
printf("sizeof(short) = %d\n", sizeof(short)); /* Om jullie er even aan te herinneren... */
audiodat = (short *) calloc(datalength, 2); /* Alloceer geheugen voor de samples */


if (audiodat == NULL)
{
printf("Niet genoeg geheugen om de samples in het geheugen te lezen.\n");
exit(0);
}


fread(audiodat, 2, datalength, in_fp);
printf("De eerste 2 samples zijn %d %d\n", audiodat[0], audiodat[1]);
printf("De laatste 2 samples zijn %d %d\n", audiodat[datalength-2], audiodat[datalength-1]);
strcpy(out_file,"out.wav");
if ((out_fp = fopen(out_file, "wb")) == NULL)
{
printf("%s is niet te openen !\n",out_file);
exit(0);
}
fwrite(&header, 44, 1, out_fp); /* Schrijf de header weg in het nieuwe bestand */
fwrite(audiodat, 2, datalength, out_fp); /* Schrijf de audio samples weg in het nieuwe bestand */
fclose (out_fp);
fclose(in_fp);
free(audiodat);

return 0;
}[/codebox]

Dit programma werkt, wat betekent dat ik een nieuw bestand out.wav krijg, voorlopig echter identiek aan test.wav. Wie kan mij op weg helpen, door bijvoorbeeld één aanpassing te schrijven (decimatie, volume-verlaging, echo-effect...) zodat ik mij hierop kan baseren voor de overige aanpassingen. Ik vertel er nog bij dat de waarden voor de aanpassingen door de gebruiker moeten kunnen worden ingegeven via het toetsenbord.

Hartelijk dank!

Dit forum kan gratis blijven vanwege banners als deze. Door te registeren zal de onderstaande banner overigens verdwijnen.

#2

jhnbk

    jhnbk


  • >5k berichten
  • 6905 berichten
  • VIP

Geplaatst op 12 april 2008 - 09:26

Je kan eens kijken naar het bestandsformaat. Hoe werkt het? En wat moet ik doen om een andere samplerate te verkrijgen.
Zoek eens naar open-source projecten; daaruit kan je meestal info halen of links naar websites.
Het vel van de beer kunnen verkopen vraagt moeite tenzij deze dood voor je neervalt. Die kans is echter klein dus moeten we zelf moeite doen.

#3

Cycloon

    Cycloon


  • >1k berichten
  • 4810 berichten
  • VIP

Geplaatst op 12 april 2008 - 09:36

Ook een KAHO student? Ik heb deze code ondertussen al op verschillende websites gevonden waarbij mensen direct de code posten en alle vragen zonder ook maar zelf een aanzet te geven.

Mss kan je al eens beginnen met hoe je zelf denkt dat het werkt of moet aangepast worden? :D

#4

Revelation

    Revelation


  • >1k berichten
  • 2364 berichten
  • Technicus

Geplaatst op 12 april 2008 - 09:39

De frequentie kun je veranderen door SamplesPerSec te veranderen. Zo te zien moet AvgBytesPerSec dan ook mee.
Het volume van een wave verander je door iedere sample keer een bepaalde magnitude te doen.
“Quotation is a serviceable substitute for wit.” - Oscar Wilde

#5

rvdp

    rvdp


  • >25 berichten
  • 43 berichten
  • Gebruiker

Geplaatst op 12 april 2008 - 10:38

De samplerate aanpassen is gelukt met onderstaande code:

[codebox] int freq;
printf("Geef nieuwe frequentie in: ");
scanf("\n%i",&freq);
header.SamplesPerSec=freq;
[/codebox]

Mono/stereo aanpassen zal ook wel lukken.

Voor de overige opgaven moet het resultaat dikwijls bekomen worden door bewerkingen (samplewaarde * factor << 1, samples met constante vermenigvuldigen,...) uit te voeren op iedere samplewaarde. Maar waar in de code kan ik deze samplewaarde terugvinden?

#6

rvdp

    rvdp


  • >25 berichten
  • 43 berichten
  • Gebruiker

Geplaatst op 12 april 2008 - 10:55

@ Cycloon: kun je de sites waar dit besproken wordt eens vermelden als het niet teveel moeite is? Vind er nl. maar 1 via Google. Dank U!

#7

Cycloon

    Cycloon


  • >1k berichten
  • 4810 berichten
  • VIP

Geplaatst op 12 april 2008 - 11:19

@ Cycloon: kun je de sites waar dit besproken wordt eens vermelden als het niet teveel moeite is? Vind er nl. maar 1 via Google. Dank U!


Op geen enkel forum heb ik echt antwoorden gezien, dus ik weet niet of je er veel aan zal hebben.

Maar ik stel voor dat je specifieke vragen stelt en dan zal je hier zeker antwoord krijgen :D

En met de samplewaarde vermoed ik dat je de samplerate bedoelt? Deze is in de struct te vinden:

long SamplesPerSec; /* No samples/sec (4 bytes) */

Veranderd door Cycloon, 12 april 2008 - 11:21


#8

rvdp

    rvdp


  • >25 berichten
  • 43 berichten
  • Gebruiker

Geplaatst op 12 april 2008 - 12:34

Om het volume aan te passen staat er letterlijk: vermenigvuldig alle samples met constante waarde.
Ik vermoed dus dat dit niet hetzelfde is als de sample rate, anders zou dit op hetzelfde neerkomen als de eerste opgave..., maar heb geen idee waar het dan wel te vinden zou zijn...

#9

Revelation

    Revelation


  • >1k berichten
  • 2364 berichten
  • Technicus

Geplaatst op 12 april 2008 - 12:58

maar heb geen idee waar het dan wel te vinden zou zijn...


De samples waar ik het over had is de daadwerkelijke data. Ik heb dit ergens gelezen, maar het was een beetje vaag beschreven.
“Quotation is a serviceable substitute for wit.” - Oscar Wilde

#10

rvdp

    rvdp


  • >25 berichten
  • 43 berichten
  • Gebruiker

Geplaatst op 12 april 2008 - 13:11

Oke, maar welke data dan?
Sorry dak ik maar blijf doorvragen over zaken die mss overduidelijk zijn, maar heb hier totaal geen ervaring mee...

Veranderd door rvdp, 12 april 2008 - 13:12


#11

Cycloon

    Cycloon


  • >1k berichten
  • 4810 berichten
  • VIP

Geplaatst op 12 april 2008 - 16:01

Zoals je hier kan zien in de code zitten de samples in audiodat:

printf("De eerste 2 samples zijn %d %d\n", audiodat[0], audiodat[1]);
fwrite(audiodat, 2, datalength, out_fp); /* Schrijf de audio samples weg in het nieuwe bestand */

Nu ben ik ook geen audio kenner dus ik weet niet echt of je gewoon die samples * waarde moet doen, maar ik vermoed van wel.

#12

rvdp

    rvdp


  • >25 berichten
  • 43 berichten
  • Gebruiker

Geplaatst op 12 april 2008 - 16:09

Ik heb nu ondertussen elke audiodat[] via een for-lus vermenigvuldigd met een bepaalde waarde, maar kan niet echt zeggen dat er een volumestijging is, eerder een vervorming die sterker wordt naarmate de constante groter wordt. Mss is dat reeds de "overflow" waarvoor gewaarschuwd werd...

Mono/stereo is ook reeds gelukt, eveneens de bestandsnaam laten verschijnen mbv argv.

Aan de rest ga ik voorlopig niet beginnen...

#13

Cycloon

    Cycloon


  • >1k berichten
  • 4810 berichten
  • VIP

Geplaatst op 12 april 2008 - 16:46

Mss is dat reeds de "overflow" waarvoor gewaarschuwd werd...


Dat vermoed ik wel als ik zo de andere vragen lees, met welke waarde vermenigvuldig je?





0 gebruiker(s) lezen dit onderwerp

0 leden, 0 bezoekers, 0 anonieme gebruikers

Ook adverteren op onze website? Lees hier meer!

Gesponsorde vacatures

Vacatures