Konvertera wav eller mp3 till C-kod

Elektronikrelaterade (på komponentnivå) frågor och funderingar.
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Konvertera wav eller mp3 till C-kod

Inlägg av thepirateboy »

Behöver lägga in några ljudklipp i min Xmega med DA-omvandlare och behöver därför konvertera
wav eller mp3 filer till en array av hexvärden. Har hittat wav2c som verkar funka om man först
konverterar filen till 8KHz, 8bit, mono.

Någon som har tips på andra program än wav2c, kanske något som gör allt på en gång?
SvenW
Inlägg: 1156
Blev medlem: 24 april 2007, 16:23:10
Ort: Göteborg

Re: Konvertera wav eller mp3 till C-kod

Inlägg av SvenW »

Sox?
Användarvisningsbild
Kubbuth
Inlägg: 161
Blev medlem: 29 mars 2011, 11:10:16
Ort: Hässelby, Stockholm

Re: Konvertera wav eller mp3 till C-kod

Inlägg av Kubbuth »

Wav behöver du egentligen bara klippa bort headern ifrån, sen är resten hex. Finns några olika format dock, signerat eller osignerat, 8/16 bit, stereo/mono samt samplerate men vet du formatet det är sparat i så funkar det fint.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Konvertera wav eller mp3 till C-kod

Inlägg av jesse »

En wav-fil är mycket enkel att läsa in och bearbeta. WAVE PCM soundfile format

Det bästa är att göra ett eget C-program som läser in filen, eventuellt sänker bitrate och bitdjup om det skulle behövas och sedan skriver ut den direkt som "kod" dvs, som en array med int.

Gjorde något liknande här om dagen då jag skulle analysera mina ljudfiler från min EKG-apparat.
Så här ser den koden ut:

(Den läser in headern tillen struct med all info - dock utnyttjar jag inte all information - programmet nedan förutsätter att jag har en kanal (mono) med 16-bitars djup. Den sänker sampelhastigheten, filtrerar ljudet och sparar i en ny fil som har fyra kanaler. Istället för att öppna en binärfil som "utfil" kan du ju öppna en textfil istället och skriva ut data som text - då är det lätt att skapa den där arrayen.)

Koden är dåligt kommenterad, då det bara är en tillfällig grej jag gjorde för att testa olika filter.
EDIT: lade till lite kommentarer (raderna med // ************** )

Kod: Markera allt

#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PATH "C:\\Documents and Settings\\Admin\\Mina dokument\\Avancerat\\ekg\\"
#define INFIL "ekg_raw.wav"
#define UTFIL "ekg_filt.wav"

    #define FILT 4
    #define RATE 600 // sampels per sekund
    #define DIV (8000/RATE)

// ************* denna struct innehåller alla data i headern från "infil" ************
struct wavefil {
    int Riff;               // 4 bytes  "RIFF"
    int ChunkSize;          // 4 bytes  bytes (36 + SubChunk2Size)
    int Format;             // 4 bytes  "WAVE"
    int SubChunk1ID;        // 4 bytes  "fmt "
    int SubChunk1Size;      // 4 bytes  16 for PCM
    short int AudioFormat;  // 2 bytes  PCM = 1 (i.e. Linear quantization)
    short int NumCHannels;  // 2 bytes  Mono = 1, Stereo = 2, etc.
    int SampleRate;         // 4 bytes  8000, 44100, etc.
    int ByteRate;           // 4 bytes  == SampleRate * NumChannels * BitsPerSample/8
    short int BlockAlign;   // 2 bytes  == NumChannels * BitsPerSample/8
    short int BitsPerSample;// 2 bytes   (8 / 16) BitsPerSample
    int Subchunk2ID;        // 4 bytes  "data"
    int Subchunk2Size;      // 4 bytes  number of bytes in the data.
} wav;


FILE *infil, *utfil;

int main() {
    printf("wave-file-resample test\n");

// ************ Öppna wave-filen för läsning ***********
    if ((infil = fopen(PATH INFIL, "rb")) == NULL) {
        printf ("File OPEN error: ");
        printf( PATH INFIL );
        return 0;
    }

    printf("\n----- " INFIL " laeses in ------\n");

    // *********** read wave header

    fread(&wav, sizeof(wav), 1, infil);

    // ************ skriv ut lite information om filen *********
    printf("\n============================================");
    printf("\nRIFF 46464952\t %x", wav.Riff);
    printf("\nChunksize\t %i", wav.ChunkSize);
    printf("\nFormat   \t %x", wav.Format);
    printf("\nSubChunk1ID\t %i", wav.SubChunk1ID);
    printf("\nSubChunk1Size\t %i", wav.SubChunk1Size);
    printf("\nAudioFormat\t %i", wav.AudioFormat);
    printf("\nNumCHannels\t %i", wav.NumCHannels);
    printf("\nSampleRate\t %i", wav.SampleRate);
    printf("\nByteRate\t %i", wav.ByteRate);
    printf("\nBlockAlign\t %i", wav.BlockAlign);
    printf("\nBitsPerSample\t %i", wav.BitsPerSample);
    printf("\nSubchunk2ID\t %i", wav.Subchunk2ID);
    printf("\nSubchunk2Size\t %i", wav.Subchunk2Size);
    printf("\n============================================\n");

// ************ beräkna tid i sekunder och  antal samplingar totalt ***********
    float total_time = wav.Subchunk2Size * 1.0 / wav.ByteRate;
    int ant_samples = wav.Subchunk2Size / wav.BlockAlign;
    printf("Total time %f sec\n", total_time);
    printf("Antal samples %i\n", ant_samples);


    //-------------------öppna utfil--------------------------//
    if ((utfil = fopen(PATH UTFIL, "wb")) == NULL) {
        printf ("Utfil OPEN error: ");
        printf( PATH UTFIL );
        return 0;
    }
        // skapa wave header *** fusk: kopierar bara infilens header ****
    fwrite(&wav, sizeof(wav), 1, utfil);
    printf("\n----- " UTFIL " skapades --------\n");

// ************* variabler för statistik och filtrering ****************
    int i, maxs,maxf,mins,minf;
    maxs = 0;
    maxf = 0;
    mins = 0;
    minf = 0;
    short int sample = 0;
    short int utsamp = 0;
    int antal_utsamp = 0;
    int filter = 0;
    int filter2 = 0;
    int filter3 = 0;
    int summa = 0;

// ******** loop: läs in ett antal samples och räkna ut medelvärdet === downsampling ******
    for (i = 0; i < ant_samples / DIV; i++) {
        int j;
        summa = 0;
        for (j=0; j< DIV; j++) {
            sample = 0;
            fread(&sample, wav.BlockAlign , 1, infil); // läser in ett sample
            summa += sample;
        }
        summa = summa / DIV; // ** medelvärdet

// ********* spara sampel i utfilen ***********
// ** spara i fyra kanaler:
// ** kanal 1: ofiltrerat - "original-ljud" fast nedsamplat
// ** kanal 2: fitrerat grad 1
// ** kanal 3: fitrerat grad 2
// ** kanal 4: fitrerat grad 3

        fwrite(&summa, wav.BlockAlign , 1, utfil); // kanal 1 original
        antal_utsamp++;

        filter = (filter * (FILT-1) / FILT) + summa;
        utsamp = filter / (FILT) ; // invertera

        fwrite(&utsamp, wav.BlockAlign , 1, utfil); // kanal 2 1:a ordningen
        antal_utsamp++;

        filter2 = (filter2 * (FILT-1) / FILT) + filter / FILT;
        utsamp = filter2 / (FILT) ; // invertera

        fwrite(&utsamp, wav.BlockAlign , 1, utfil); // kanal 3 2:a ordningen
        antal_utsamp++;

        filter3 = (filter3 * (FILT-1) / FILT) + filter2 / FILT;
        utsamp = filter3 / (FILT) ; // invertera

        fwrite(&utsamp, wav.BlockAlign , 1, utfil); // kanal 4 3:e ordningen
        antal_utsamp++;

        if ((i & 127) == 0) printf("block %i\t\t\r", (i >> 7)); // skriv ut i konsolen hur långt jag kommit
    }
    printf("\n");
    int antal_bytes = antal_utsamp * wav.BlockAlign;
    /* ******* tänkte rätta till utfil-headern i efterhand, men det blev fel nånstans
         ****** så det blir bortkommenterat just nu
    fseek(utfil, +4, SEEK_SET); // flytta till ChunkSize
    fwrite(&antal_bytes+36, 4 , 1, utfil); // antal totalt
    fseek(utfil, +36, SEEK_SET); // flytta till ChunkSize
    fwrite(&antal_bytes, 4 , 1, utfil); // antal data */

    fclose(infil);
    fclose(utfil);
    printf("\nklart!");
    return 0;
}
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Re: Konvertera wav eller mp3 till C-kod

Inlägg av thepirateboy »

Är nybörjare på det här med ljud så jag har lite att lära.

Både SOX och kodexemplet kan nog komma till nytta i det här projektet.

Tackar!
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Konvertera wav eller mp3 till C-kod

Inlägg av jesse »

Särskilt länken överst i mitt inlägg ovan är värdefull för att förstå wave-filer. :tumupp:

Koden tog jag med för jag tänkte den kunde vara lätt att bygga vidare på. Det räcker egentligen att du ändrar "binärfil" till "textfil" på utfilen, och tar bort mina filter, sedan är det ju bara att skriva ut sampels med fprintf (utfil, "%i,", i); så får du ju en array om du lägger till { och } före och efter.

En wave-fil som är i mono och har 16-bitar per sample, 11025 samples per sekund innehåller, efter de 44 bytena i headern 22050 bytes data.

Dessa bytes är uppdelade i 11025 "word" - dvs 16-bitars tal. Varje tal är ett 'sample' som anger amplituden på signalen i just det ögonblicket i formatet 16 bitars signed int (toppvärden mellan -32767 och +32768)

Sampelhastigheten syns inte i själva datan - den är bara en siffra i headern som talar om hur snabbt du ska spela upp den. I det här fallet - om du har en fil som är 2 sekunder lång kommer den att innehålla 22050 samples = 44100 bytes data.
Användarvisningsbild
Syncro
Inlägg: 100
Blev medlem: 17 mars 2010, 21:25:40
Ort: Helsingborg

Re: Konvertera wav eller mp3 till C-kod

Inlägg av Syncro »

WAV kan iochförsig innehålla komprimerad data, se t.ex.

http://en.wikipedia.org/wiki/WAV#WAV_fi ... s_compared

Se även http://www.partnersinrhyme.com/pc/pcConvert.shtml där länk finns till "Wham 1.3.3" som tydligen kan konvertera från WAV till bl.a. råformat enligt uppgift, har du det i råformat så är ju saken sedan i princip biff.

Hoppas detta kan hjälpa.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Konvertera wav eller mp3 till C-kod

Inlägg av jesse »

Nu kan man lätt kolla det genom att läsa byte nr 20+21 ur headern (16 bitars unsigned int).
Är det en etta så är det vanligt okomprimerar format.

Kod: Markera allt

20        2   AudioFormat      PCM = 1 (i.e. Linear quantization)
                               Values other than 1 indicate some 
                               form of compression.
Om man bara väljer att spara wave-filen utan komprimering eller udda format, så blir det ju en "vanlig" wav-fil.
"Råformat" har ju exakt samma innehåll som en okomprimerad wav, förutom de 44 bytena i headern.
Användarvisningsbild
adent
Inlägg: 4245
Blev medlem: 27 november 2008, 22:56:23
Ort: Utanför Jönköping
Kontakt:

Re: Konvertera wav eller mp3 till C-kod

Inlägg av adent »

När jag meckade med wav-filer så sparade jag dem som 8-bitars mono i Audacity (mycket bra program) och lade dem på SD-kort
och lät microprocessorn läsa in dem och skicka till D/A:n. Eftersom jag visste vad det var för filer och 8-bitars mono så sket jag
i headern och bara tryckte ut dem, jag märkte inte ens nån störning i början av headern :)

så ett cprogram i stil med (edit: kompilerar och fungerar, iaf i netbsd):

Kod: Markera allt

#include <stdio.h>

int main(void)
{
   unsigned char buf;
   int bytes = 0;

   FILE *f = fopen("fil.wav","r");

   printf("unsigned char sound[MISSING] = {\n");
   while(!feof(f))
   {
      fread(&buf, 1,1, f);
      printf("%d,\n", buf);
      bytes++;
   }
   fclose(f);

   printf("};\n\n");

   printf("Fyll i detta innanför []:arna längst upp: %d\n", bytes);
   return 0;
}

}
MVH: Mikael
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Re: Konvertera wav eller mp3 till C-kod

Inlägg av thepirateboy »

Ja, det var ju inte så svårt det där. Det enda trubbel jag hade var att redigeringsprogrammet Audacity
envisades med att lägga till metadata (artist, låt etc.) i headern så det blev problem att läsa filen.

Lyckades dock ändra inställningar i Audacity så detta aldrig kom med i headern, och då blev det enklare.

Eftersom jag tycker bättre om att klicka med musen än köra "command line program" så gjorde jag ett
litet C# program. Är ganska otestat så det kan finnas buggar. Bifogar källkoden ifall någon vill bygga vidare.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
MiaM
Inlägg: 12850
Blev medlem: 6 maj 2009, 22:19:19

Re: Konvertera wav eller mp3 till C-kod

Inlägg av MiaM »

Dum fråga:

Vad är det för ruttna kompilatorer som inte kan inkludera en binärklump i koden? (Ja, jag inser att de flesta kompilatorer är säkert ruttna ur det här avseendet).

Jag minns inte exakt syntaxen men minns mycket väl att när man körde K-SEKA / ASM-One & co på Amigatiden så kunde man inkludera en binärfil på valfritt ställe i sin kod. Visserligen assembler och inte c, men ändå.
sodjan
EF Sponsor
Inlägg: 43249
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Konvertera wav eller mp3 till C-kod

Inlägg av sodjan »

Och vad hände med den?
Förväntade man sig ett visst innehåll/format?
Användarvisningsbild
Kubbuth
Inlägg: 161
Blev medlem: 29 mars 2011, 11:10:16
Ort: Hässelby, Stockholm

Re: Konvertera wav eller mp3 till C-kod

Inlägg av Kubbuth »

Nä, det var bara hårda data, exakt som filen var sparad, kunde vara kod man anropade eller datasatser som till exempel grafik eller ljud, helt upp till dig.
Användarvisningsbild
AndLi
Inlägg: 18254
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Konvertera wav eller mp3 till C-kod

Inlägg av AndLi »

Det kan väll inte vara kompilatorns jobb att inkludera binärklumpar? Det borde väll vara länkaren som skulle kunna fixa sånt?
Nerre
Inlägg: 27195
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Konvertera wav eller mp3 till C-kod

Inlägg av Nerre »

Det blir ju problem om filen innehåller 0x00 och andra tecken (i C så lär ju ett semikolon eller citationstecken innebära problem).
Skriv svar