1 van 1

[c] wav-bestand manipuleren

Geplaatst: za 12 apr 2008, 10:18
door rvdp
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:

Code: Selecteer alles

#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;

}
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!

Re: [c] wav-bestand manipuleren

Geplaatst: za 12 apr 2008, 10:26
door jhnbk
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.

Re: [c] wav-bestand manipuleren

Geplaatst: za 12 apr 2008, 10:36
door Cycloon
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

Re: [c] wav-bestand manipuleren

Geplaatst: za 12 apr 2008, 10:39
door Revelation
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.

Re: [c] wav-bestand manipuleren

Geplaatst: za 12 apr 2008, 11:38
door rvdp
De samplerate aanpassen is gelukt met onderstaande code:

Code: Selecteer alles

 int freq;

    printf("Geef nieuwe frequentie in: ");

    scanf("\n%i",&freq);

    header.SamplesPerSec=freq;

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?

Re: [c] wav-bestand manipuleren

Geplaatst: za 12 apr 2008, 11:55
door rvdp
@ 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!

Re: [c] wav-bestand manipuleren

Geplaatst: za 12 apr 2008, 12:19
door Cycloon
@ 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:

Code: Selecteer alles

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

Re: [c] wav-bestand manipuleren

Geplaatst: za 12 apr 2008, 13:34
door rvdp
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...

Re: [c] wav-bestand manipuleren

Geplaatst: za 12 apr 2008, 13:58
door Revelation
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.

Re: [c] wav-bestand manipuleren

Geplaatst: za 12 apr 2008, 14:11
door rvdp
Oke, maar welke data dan?

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

Re: [c] wav-bestand manipuleren

Geplaatst: za 12 apr 2008, 17:01
door Cycloon
Zoals je hier kan zien in de code zitten de samples in audiodat:

Code: Selecteer alles

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.

Re: [c] wav-bestand manipuleren

Geplaatst: za 12 apr 2008, 17:09
door rvdp
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...

Re: [c] wav-bestand manipuleren

Geplaatst: za 12 apr 2008, 17:46
door Cycloon
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?