Author | Message | Time |
---|---|---|
iago | My friend is looking for a program which can scan through a folder of mp3's (thousands, likely), and grab the bitrate, and list them in a file. A) Does anybody know if such a program exists? B) Anybody know the format of an mp3 header so I can just grab it manually? thanks! -iago | December 2, 2003, 4:13 AM |
warz | Maybe this will help you create a program that loops through a directory, and finds bitrates. http://www.pscode.com/vb/scripts/ShowCode.asp?txtCodeId=512&lngWId=3 | December 2, 2003, 4:17 AM |
Skywing | What about variable-bitrate files? | December 2, 2003, 4:19 AM |
iago | [quote author=warz link=board=2;threadid=4009;start=0#msg33134 date=1070338657] Maybe this will help you create a program that loops through a directory, and finds bitrates. http://www.pscode.com/vb/scripts/ShowCode.asp?txtCodeId=512&lngWId=3 [/quote] Wow, a good answer in 4 minutes. Damn people here are l33t :) Thanks, I'm sure that'll work, or can be modified nicely! | December 2, 2003, 4:23 AM |
iago | [quote author=Skywing link=board=2;threadid=4009;start=0#msg33136 date=1070338784] What about variable-bitrate files? [/quote] He'll get over it. | December 2, 2003, 4:23 AM |
iago | I deleted my old post, since I changed my program substantially. Here is the new one: [code]// MP3Checker.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <windows.h> struct FrameHeader { BYTE AudioVersionID; BYTE LayerDescription; BYTE Protection; BYTE Bitrate; BYTE SamplingFrequency; BYTE Padding; BYTE Private; BYTE ChannelMode; BYTE ModeExtension; BYTE Copyright; BYTE Original; BYTE Emphasis; }; // Extracts a series of bits from a byte int GetBits(unsigned int byte, BYTE start, BYTE length) { byte = byte << (32 - (start + length)); byte = byte >> (32 - (start + length)); byte = byte >> start; return byte; } int GetBits(unsigned int byte, BYTE start, BYTE length, BYTE size) { byte = byte << (size - (start + length)); byte = byte >> (size - (start + length)); byte = byte >> start; return byte; } bool GetMP3Info(char *Filename, FrameHeader *Header) { // the current byte while scanning the file BYTE ch; // the file printf("Opening file: %s\n", Filename); FILE *File = fopen(Filename, "rb"); // where in the file we are int loc = 0; if(File == NULL) { printf("Error: file not found\n"); return false; } // First, we have to find the byte 0xFF printf("Scanning for 0xFF\n"); while((ch = getc(File)) != 0xFF) { loc++; //printf("%02X ", ch); } printf("Found @ %d\n", loc); ungetc(ch, File); DWORD Data; fread(&Data, 1, 4, File); // The byte order is read in in Big-Endian, so fix that Data = (Data & 0x000000FF) << 24 | (Data & 0x0000FF00) << 8 | (Data & 0x00FF0000) >> 8 | (Data & 0xFF000000) >> 24; //printf("Data = %08X", Data); printf("Setting the header\n"); Header->AudioVersionID = GetBits(Data, 19, 2); Header->LayerDescription = GetBits(Data, 17, 2); Header->Protection = GetBits(Data, 16, 1); Header->Bitrate = GetBits(Data, 12, 4); Header->SamplingFrequency = GetBits(Data, 10, 2); Header->Padding = GetBits(Data, 9, 1); Header->Private = GetBits(Data, 8, 1); Header->ChannelMode = GetBits(Data, 6, 2); Header->ModeExtension = GetBits(Data, 4, 2); Header->Copyright = GetBits(Data, 3, 1); Header->Original = GetBits(Data, 2, 1); Header->Emphasis = GetBits(Data, 0, 2); printf("Closing %s\n", Filename); if(File) { fclose(File); } return true; } char *Version[] = { "Version 2.5", "Reserved", "Version 2", "Version 1" }; char *Layer[] = { "Reserved", "Layer III", "Layer II", "Layer I" }; char *Protection[] = { "Protected", "Not Protected" }; // Assuming MP3 char *BitRate[] = { "Variable", "32", "40", "48", "56", "64", "80", "96", "112", "128", "160", "192", "224", "256", "320", "Bad" }; double SampleRate[] = { 44.1, 48.0, 32.0, -1 }; char *ChannelMode[] = { "Stereo", "Joint stereo", "Dual channel", "Single channel" }; char *Copyright[] = { "Copyrighted", "Not copyrighted" }; //#define pause #define MAXLEN 1024 int main(int argc, char* argv[]) { FrameHeader *fh = new FrameHeader; FILE *out; char File[MAXLEN]; printf("Checking if output file exists...\n"); if((out = fopen("out.csv", "r")) == NULL) { // Create the file if it doesn't exist printf("out.csv not found; creating\n"); out = fopen("out.csv", "w"); fprintf(out, "Filename, Version, Layer, Protection, Bitrate, Samplerate, Channel Mode, Copyright\n"); } else { fclose(out); out = fopen("out.csv", "a"); } //fgets(File, MAXLEN, stdin); while(fgets(File, MAXLEN, stdin) != NULL) { strtok(File, "\n"); printf("Processing: %s\n", File); printf("Getting info...\n"); if(GetMP3Info(File, fh) == false) { printf("Invalid file; skipping\n"); fprintf(out, "Invalid file format\n", File); #ifdef pause system("pause"); #endif } else { //FILE *out = fopen("out.csv", "a"); //printf("Outputting data\n"); printf("Outputting data: %d, %d, %d, %d, %d, %d, %d\n", fh->AudioVersionID, fh->LayerDescription, fh->Protection, fh->Bitrate, fh->SamplingFrequency, fh->ChannelMode, fh->Copyright); fprintf(out, "%s, %s, %s, %s, %s, %.1f, %s, %s\n", File, Version[fh->AudioVersionID], Layer[fh->LayerDescription], Protection[fh->Protection], BitRate[fh->Bitrate], SampleRate[fh->SamplingFrequency], ChannelMode[fh->ChannelMode], Copyright[fh->Copyright] ); } printf("\n"); } printf("Closing output file\n"); fclose(out); printf("Done!\n\n"); system("pause"); return 0; } [/code] Note that it expects to recieve the filenames on stdin, so here's what you should do: To scan this folder+all subfolders for mp3's: dir /o/s/b/a-d *.mp3 | MP3Checker.exe To scan entire drive (say, C drive): dir /o/s/b/a-d c:\*.mp3 | MP3Checker.exe :) | December 3, 2003, 4:37 AM |
Arta | Instead of GetBits, can't you do: [code] struct FrameHeader { BYTE FirstField:2, SecondField:6; BYTE SomethingElse:4, SecondHalfOfSomethingElse:4; ... } [/code] And then do: [code] FrameHeader *Header = (FrameHeader*)Data; [/code] ? | December 3, 2003, 2:25 PM |
iago | I didn't know you could declare something as only certain bits. And if you can, is it portable across platorms? Doing it like this is fine, anyway, but that's not a bad idea :) | December 3, 2003, 2:37 PM |
Arta | Pretty sure it's standard. | December 3, 2003, 3:45 PM |
Yoni | Yes, it's called a bit field, and it's standard C. | December 4, 2003, 8:13 PM |
iago | Well anywhere, I plan to work more on this later. What I want to do is add support to reading ID3 and ID3v2 tags, and allow the user to choose which fields to output. This way, people can make a quick database of their music which they can either refer to or they can share with friends and such. I think Grok discussed something like this before, on my forum, but for movies. But I still think this would be neat :) | December 4, 2003, 10:08 PM |
Myndfyr | [quote author=iago link=board=2;threadid=4009;start=0#msg33133 date=1070338405] My friend is looking for a program which can scan through a folder of mp3's (thousands, likely), and grab the bitrate, and list them in a file. A) Does anybody know if such a program exists? B) Anybody know the format of an mp3 header so I can just grab it manually? thanks! -iago [/quote] So - is this mysterious friend really yourself?!? | December 5, 2003, 12:05 AM |
iago | No, I have exactly one mp3 (thanks, warz, for the beta theme song!). My friend is a guy I go to school with. | December 5, 2003, 12:42 AM |
warz | beta theme song kicks ass! ;) | December 5, 2003, 4:15 AM |
iago | And it happened to be sitting on my desktop when I needed a guinui-pig mp3 :) | December 5, 2003, 4:44 AM |
Adron | [quote author=iago link=board=2;threadid=4009;start=0#msg33674 date=1070575736] I think Grok discussed something like this before, on my forum, but for movies. But I still think this would be neat :) [/quote] I might have offered to make a tool to read id3 tags and submit them to the central reference database. Something like the tool you're now making ;) | December 5, 2003, 1:36 PM |
iago | This project has been bumped back to #2 now, since it works to my friends satisfaction, and I've been updated my Starcraft Plugin (finally) | December 5, 2003, 10:21 PM |