Sida 1 av 2
Konvertera wav eller mp3 till C-kod
Postat: 21 mars 2012, 08:06:38
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?
Re: Konvertera wav eller mp3 till C-kod
Postat: 21 mars 2012, 08:17:13
av SvenW
Sox?
Re: Konvertera wav eller mp3 till C-kod
Postat: 21 mars 2012, 08:56:48
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.
Re: Konvertera wav eller mp3 till C-kod
Postat: 21 mars 2012, 09:31:18
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;
}
Re: Konvertera wav eller mp3 till C-kod
Postat: 21 mars 2012, 09:59:37
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!
Re: Konvertera wav eller mp3 till C-kod
Postat: 21 mars 2012, 10:12:50
av jesse
Särskilt länken överst i mitt inlägg ovan är värdefull för att förstå wave-filer.
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.
Re: Konvertera wav eller mp3 till C-kod
Postat: 21 mars 2012, 19:14:53
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.
Re: Konvertera wav eller mp3 till C-kod
Postat: 21 mars 2012, 19:24:59
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.
Re: Konvertera wav eller mp3 till C-kod
Postat: 21 mars 2012, 22:51:27
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
Re: Konvertera wav eller mp3 till C-kod
Postat: 9 april 2012, 20:17:21
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.
Re: Konvertera wav eller mp3 till C-kod
Postat: 9 april 2012, 23:28:22
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å.
Re: Konvertera wav eller mp3 till C-kod
Postat: 9 april 2012, 23:32:49
av sodjan
Och vad hände med den?
Förväntade man sig ett visst innehåll/format?
Re: Konvertera wav eller mp3 till C-kod
Postat: 10 april 2012, 08:03:40
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.
Re: Konvertera wav eller mp3 till C-kod
Postat: 10 april 2012, 08:48:26
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?
Re: Konvertera wav eller mp3 till C-kod
Postat: 10 april 2012, 09:26:04
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).