| Autor |
Beitrag |
ACID
      
Beiträge: 53
D7 Pers
|
Verfasst: Do 28.07.05 08:25
Habe den quellcode von www.delphi-forum.de/viewtopic.php?t=16228 ausprobiert aber der zeigt mir nichts an. Dann habe ich den Code vom Easy-Helper von www.delphi-total.de/eh/ ausprobiert und der zeigt mir auch nichts an.
Leider weiss ich nicht mehr weiter. Kann mir jemand weiterhelfen, oder hat jemand ein kleines Demoprogramm mit Source-Code wo dies beschrieben ist?
Bitte helft mir!!!
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 480
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Do 28.07.05 08:35
Der beschriebene Code soll ja auch gar nichts anzeigen. Er soll nur was auslesen.
Anzeigen geht z.B. so:
Delphi-Quelltext 1: 2:
| mp3Info(myfilename,mpeginfo,ID3v2Tag,id3v1tag); showmessage(ID3v1Tag.Artist); |
_________________ We are, we were and will not be.
|
|
Heiko
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Do 28.07.05 09:23
Beispielprogramme und ein paar Units dazu findest du hier (Ich glaube das war die, ich kann gerade nicht nachgucken, da die Seite gerade offline ist).
|
|
BennyM
      
Beiträge: 45
|
Verfasst: Do 04.08.05 10:26
es gibt auch bei den jedi komponenten im register "jv non-visual" eine komponente dafür
|
|
F34r0fTh3D4rk
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Do 04.08.05 11:15
der code ausm easy helper funktioniert, nur haben die Strings immer die gleiche länge (30), deshalb ist es nicht so einfach Interpret und Titel zusammenzufügen:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128:
| Type TID3Tag = record ID: string[3]; Titel: string[30]; Artist: string[30]; Album: string[30]; Year: string[4]; Comment: string[30]; Genre: byte; dauer: longint; sample: integer; bits: byte; vers: byte; layers: byte; end;
const MPEG_BIT_RATES : array[1..3] of array[1..3] of array[0..15] of word = (((0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0), (0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0), (0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,0)), ((0,32,48, 56, 64, 80, 96,112,128,144,160,176,192,224,256,0), (0, 8,16,24, 32, 40, 48, 56, 64, 80, 96, 112,128,144,160,0), (0, 8,16,24, 32, 40, 48, 56, 64, 80, 96, 112,128,144,160,0)), ((0,32,48, 56, 64, 80, 96,112,128,144,160,176,192,224,256,0), (0, 8,16,24, 32, 40, 48, 56, 64, 80, 96, 112,128,144,160,0), (0, 8,16,24, 32, 40, 48, 56, 64, 80, 96, 112,128,144,160,0)));
sample_rates: array[1..3] of array [0..3] of word= ((44100,48000,32000,0), (22050,24000,16000,0), (11025,12000,8000,0));
Es folgt die eigentliche "Auslese" Procedure:
var ID3Tag: TID3Tag;
procedure Lese_ID3Tag(Filename: string); var Buffer: array[1..128] of char; F: File; mp3hdrread: array[1..4] of byte; mp3hdr: longint absolute mp3hdrread; tempbyte, bitrateindex, versionindex: byte; bitrate, version, layer, groese: longint; begin AssignFile(F, Filename);
Reset(F,1); groese:=filesize(f); blockread(f,mp3hdrread,4); tempbyte:=mp3hdrread[1]; mp3hdrread[1]:=mp3hdrread[4]; mp3hdrread[4]:=tempbyte; tempbyte:=mp3hdrread[2]; mp3hdrread[2]:=mp3hdrread[3]; mp3hdrread[3]:=tempbyte;
reset(f,1); Seek(F,FileSize(F)-128); BlockRead(F, Buffer, SizeOf(Buffer)); CloseFile(F); bitrateindex:=((mp3hdr shr 12) and $F); versionindex:=((mp3hdr shr 19) and $3);
case versionindex of 0: version:=3; 1: version:=0; 2: version:=2; 3: version:=1; end;
layer:=4-((mp3hdr shr 17) and $3);
if version<>0 then bitrate:=MPEG_BIT_RATES[version][layer][bitrateindex] else bitrate:=128;
with ID3Tag do begin ID:=copy(Buffer,1,3); Titel:=copy(Buffer,4,30); Artist:=copy(Buffer,34,30); Album:=copy(Buffer,64,30); Year:=copy(Buffer,94,4); Comment:=copy(Buffer,98,30); Genre:=ord(Buffer[128]); sample:=sample_rates[version][((mp3hdr shr 10) and $3)]; dauer:=(groese*8) div ((bitrate)*1000); bits:=bitrate; vers:=version; layers:=layer; end; end;
Die Procedure kann man dann folgendermaßen Anwenden:
procedure TForm1.Button1Click(Sender: TObject); begin if OpenDialog1.Execute then begin Lese_ID3Tag(OpenDialog1.FileName);
Titel.Caption:=ID3Tag.Titel; Artist.Caption:=ID3Tag.Artist; Album.Caption:=ID3Tag.Album; Year.Caption:=ID3Tag.Year; Comment.Caption:=ID3Tag.Comment; Genre.Caption:=IntToStr(ID3Tag.Genre);
Duration.Caption:=IntToStr(id3tag.dauer); Samplerate.Caption:=IntToStr(id3tag.sample); Bitrate.Caption:=IntToStr(id3tag.bits); Layer.caption:=IntToStr(id3tag.layers); Yersion.caption:=IntToStr(id3tag.vers); end; end; |
Ich kürze das so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| function Cut(str: string): string; var i: integer; begin for i := length(str) downto 1 do if ord(str[i]) <> 0 then begin result := copy(str, 1, i); break; end; end; |
Delphi-Quelltext 1: 2: 3:
| Artist := Cut(ID3Tag.Artist); Title := Cut(ID3Tag.Title); Fullname := Artist + ' - ' + Title; |
Zuletzt bearbeitet von F34r0fTh3D4rk am Do 04.08.05 16:04, insgesamt 1-mal bearbeitet
|
|
Heiko
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Do 04.08.05 11:27
Diese Variante würde ich dir auch noch aus einem anderem Grund nicht empfehlen. Es gibt bei mp3s auch eine freeformat-Komprimierung (freie wählbare Bitrate) und da kann ich dir nicht sagen wie der Code reagiert.
|
|
F34r0fTh3D4rk
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Do 04.08.05 11:39
Hast du da ne bessere Lösung ? (heeer damit  )
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 480
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Do 04.08.05 13:36
@F34r0fTh3D4rk: Der Codeteil zum Bestimmen der Länge funktioniert grob gesagt nur in einigen wenigen Spezialfällen.
Erstens: Es wird davon ausgegangen, dass der erste MPEG-HEader am Anfang der Datei steht (zumindest lese ich das aus dem Code raus.)
Das muss aber nicht so sein, und ist sehr oft auch nicht so. Sehr häufig steht dort der ID3v2-Tag, der fast beliebig lang sein kann (afaik bis zu 256MB) oder - wenn dieser nachträglich gelöscht wurde - unter Umständen nur entsprechend viele 0en.
Zweitens: Bei VBR-Files ist der erste MPEG-Fram kein echter Audio-Frame, sondern wird von vielen Encodern als Speicherort für diverse andere Dinge benutzt, z.B. durchschnittliche Bitrate, Anzahl der Frames (=> Längenberechnung möglich), und ein Sprungstellen-Array. es ist zwar ein gültiger MPEG-Frame mit richtigem Header, aber die Header-Informationen dieses Frames geben keine Info über die eigentliche Datei.
Die oben verlinkte Prozedur von mir ist zwar ein Monstrum, aber diese Dinge werden dort berücksichtigt.
_________________ We are, we were and will not be.
|
|
F34r0fTh3D4rk
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Do 04.08.05 15:22
welche ? die aus dem ersten Beitrag ? Die unit ?
Kompiliert er nicht, TMPEGHeader kennt er zB nicht, trim, exists, dateigroesse und sample_rates ebenfalls
eine andere unit sieht so aus:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113:
| unit ID3;
interface
{$A+} {$Z1}
type ID3Genre = ( id3gBlues, id3gClassicRock, id3gCountry, id3gDance, id3gDisco, id3gFunk, id3gGrunge, id3gHipHop, id3gJazz, id3gMetal, id3gNewAge, id3gOldies, id3gOther, id3gPop, id3gRNB, id3gRap, id3gReggae, id3gRock, id3gTechno, id3gIndustrial, id3gAlternative, id3gSka, id3gDeathMetal, id3gPranks, id3gSoundtrack, id3gEuroTechno, id3gAmbient, id3gTripHop, id3gVocal, id3gJazzFunk, id3gFusion, id3gTrance, id3gClassical, id3gInstrumental, id3gAcid, id3gHouse, id3gGame, id3gSoundClip, id3gGospel, id3gNoise, id3gAlternRock, id3gBass, id3gSoul, id3gPunk, id3gSpace, id3gMeditative, id3gInstrumentalPop, id3gInstrumentalRock, id3gEthnic, id3gGothic, id3gDarkwave, id3gTechnoIndustrial, id3gElectronic, id3gPopFolk, id3gEurodance, id3gDream, id3gSouthernRock, id3gComedy, id3gCult, id3gGangsta, id3gTop40, id3gChristianRap, id3gPopFunk, id3gJungle, id3gNativeAmerican, id3gCabaret, id3gNewWave, id3gPsychadelic, id3gRave, id3gShowtunes, id3gTrailer, id3gLoFi, id3gTribal, id3gAcidPunk, id3gAcidJazz, id3gPolka, id3gRetro, id3gMusical, id3gRockNRoll, id3gHardRock, id3gFolk, id3gFolkRock, id3gNationalFolk, id3gSwing, id3gFastFusion, id3gBebob, id3gLatin, id3gRevival, id3gCeltic, id3gBluegrass, id3gAvantgarde, id3gGothicRock, id3gProgressiveRock, id3gPsychedelicRock, id3gSymphonicRock, id3gSlowRock, id3gBigBand, id3gChorus, id3gEasyListening, id3gAcoustic, id3gHumour, id3gSpeech, id3gChanson, id3gOpera, id3gChamberMusic, id3gSonata, id3gSymphony, id3gBootyBass, id3gPrimus, id3gPornGroove, id3gSatire, id3gSlowJam, id3gClub, id3gTango, id3gSamba, id3gFolklore, id3gBallad, id3gPowerBallad, id3gRhythmicSoul, id3gFreestyle, id3gDuet, id3gPunkRock, id3gDrumSolo, id3gAcapella, id3gEuroHouse, id3gDanceHall ); ID3Struct = packed record Magic: array [0..2 ] of Char; Title: array [0..29] of Char; Artist: array [0..29] of Char; Album: array [0..29] of Char; Year: array [0..3 ] of Char; Comment: array [0..29] of Char; Genre: ID3Genre; end;
const ID3Magic = 'TAG'; ID3OffsetFromEnd = 128; ID3UnknowGenre = ID3Genre(255); ID3GenreName: array [ID3Genre] of PChar = ( 'Blues', 'Classic Rock', 'Country', 'Dance', 'Disco', 'Funk', 'Grunge', 'Hip-Hop', 'Jazz', 'Metal', 'New Age', 'Oldies', 'Other', 'Pop', 'R&B', 'Rap', 'Reggae', 'Rock', 'Techno', 'Industrial', 'Alternative', 'Ska', 'Death Metal', 'Pranks', 'Soundtrack', 'Euro-Techno', 'Ambient', 'Trip-Hop', 'Vocal', 'Jazz+Funk', 'Fusion', 'Trance', 'Classical', 'Instrumental', 'Acid', 'House', 'Game', 'Sound Clip', 'Gospel', 'Noise', 'AlternRock', 'Bass', 'Soul', 'Punk', 'Space', 'Meditative', 'Instrumental Pop', 'Instrumental Rock', 'Ethnic', 'Gothic', 'Darkwave', 'Techno-Industrial', 'Electronic', 'Pop-Folk', 'Eurodance', 'Dream', 'Southern Rock', 'Comedy', 'Cult', 'Gangsta', 'Top 40', 'Christian Rap', 'Pop/Funk', 'Jungle', 'Native American', 'Cabaret', 'New Wave', 'Psychadelic', 'Rave', 'Showtunes', 'Trailer', 'Lo-Fi', 'Tribal', 'Acid Punk', 'Acid Jazz', 'Polka', 'Retro', 'Musical', 'Rock & Roll', 'Hard Rock', 'Folk', 'Folk-Rock', 'National Folk', 'Swing', 'Fast Fusion', 'Bebob', 'Latin', 'Revival', 'Celtic', 'Bluegrass', 'Avantgarde', 'Gothic Rock', 'Progressive Rock', 'Psychedelic Rock', 'Symphonic Rock', 'Slow Rock', 'Big Band', 'Chorus', 'Easy Listening', 'Acoustic', 'Humour', 'Speech', 'Chanson', 'Opera', 'Chamber Music', 'Sonata', 'Symphony', 'Booty Bass', 'Primus', 'Porn Groove', 'Satire', 'Slow Jam', 'Club', 'Tango', 'Samba', 'Folklore', 'Ballad', 'Power Ballad', 'Rhythmic Soul', 'Freestyle', 'Duet', 'Punk Rock', 'Drum Solo', 'Acapella', 'Euro-House', 'Dance Hall' );
function GetMP3Infos(FN:String): id3struct;
implementation
function GetMP3Infos(FN:String): id3struct; var F: File of Byte; Tag: ID3Struct; HasTag: Boolean; GenreName: String; NewFN: String; const Tab = #9; begin AssignFile(F, fn); try Reset(F); try Seek(F, FileSize(F) - ID3OffsetFromEnd); BlockRead(F, Tag, SizeOf(Tag)); HasTag := Tag.Magic = ID3Magic; if not HasTag then begin FillChar(Tag, Sizeof(Tag), ' '); Tag.Magic := ID3Magic; Tag.Genre := ID3UnknowGenre; end; CloseFile(f); Result:=Tag; except end; except end; end;
end. |
ok jetzt sinds nur noch 2 compiler fehler:
| Zitat: |
[Fehler] Unit1.pas(131): Bei der vorherigen Deklaration von GetFramelength wurde die Direktive 'overload' nicht angegeben
[Fehler] Unit1.pas(312): Undefinierter Bezeichner: 'exists'
[Fehler] Unit1.pas(317): Undefinierter Bezeichner: 'exists'
[Fehler] Unit1.pas(342): Undefinierter Bezeichner: 'exists'
[Fehler] Unit1.pas(346): Undefinierter Bezeichner: 'exists'
|
Das mit dem exists konnte ich beheben, bleibt noch das:
| Zitat: |
[Fehler] Unit1.pas(131): Bei der vorherigen Deklaration von GetFramelength wurde die Direktive 'overload' nicht angegeben
|
hab beiden overload angefügt und er kompiliert
so scheint es korrekt zu sein:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516: 517: 518: 519: 520: 521: 522: 523: 524: 525: 526: 527: 528: 529: 530: 531: 532: 533: 534: 535: 536: 537: 538: 539: 540: 541: 542: 543: 544: 545: 546: 547: 548: 549: 550: 551: 552: 553: 554: 555: 556: 557: 558: 559: 560: 561: 562: 563: 564: 565: 566: 567: 568: 569: 570: 571: 572: 573: 574: 575: 576: 577: 578: 579: 580: 581: 582: 583: 584: 585: 586: 587: 588: 589: 590: 591: 592: 593: 594: 595: 596: 597: 598: 599: 600: 601: 602: 603: 604: 605: 606: 607: 608: 609: 610: 611: 612: 613: 614: 615: 616: 617: 618: 619: 620: 621: 622: 623: 624: 625: 626: 627: 628: 629: 630: 631: 632: 633: 634: 635: 636: 637: 638: 639: 640: 641: 642: 643: 644: 645: 646: 647: 648: 649: 650: 651: 652: 653:
| unit Unit1;
interface
uses sysutils;
type TBuffer = Array of byte; TMPEGHeader = array[1..4] of byte; TID3v1Tag = record exists: boolean; ID: string[3]; Titel: string[30]; Artist: string[30]; Album: string[30]; Year: string[4]; Comment: string[30]; Track: byte; Genre: byte; end;
TID3v2Tag = record exists: boolean; artist: string; titel: string; album: string; end;
TMPEGInfo = record dateigroesse:longword; Position: integer; Version: integer; Layer: integer; Protection: boolean; Bitrate: integer; Samplerate: integer; ChannelMode: byte; Extension: byte; Copyright: boolean; Original: boolean; Emphasis: byte; Frames: longint; Dauer: longint; VBR: boolean; end;
const MPEG_BIT_RATES: array[1..3] of array[1..3] of array[0..15] of word = (( (0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0), (0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0), (0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,0)), ((0,32,48, 56, 64, 80, 96,112,128,144,160,176,192,224,256,0), (0, 8,16,24, 32, 40, 48, 56, 64, 80, 96, 112,128,144,160,0), (0, 8,16,24, 32, 40, 48, 56, 64, 80, 96, 112,128,144,160,0)), ((0,32,48, 56, 64, 80, 96,112,128,144,160,176,192,224,256,0), (0, 8,16,24, 32, 40, 48, 56, 64, 80, 96, 112,128,144,160,0), (0, 8,16,24, 32, 40, 48, 56, 64, 80, 96, 112,128,144,160,0) ));
SAMPLE_RATES: array[1..3] of array [0..3] of word = ( (44100, 48000, 32000, 0), (22050, 24000, 16000, 0), (11025, 12000, 8000, 0) );
CHANNEL_MODES: array[0..3] of string = ( 'Stereo', 'Joint stereo', 'Dual channel (Stereo)', 'Single channel (Mono)' );
EXTENSIONS: array[1..3] of array [0..3] of string = ( ('bands 4 to 31', 'bands 8 to 32', 'bands 12 to 31', 'bands 16 to 31'), ('bands 4 to 31', 'bands 8 to 32', 'bands 12 to 31', 'bands 16 to 31'), ('IS:off, MS:off', 'IS:on, MS:off', 'IS:off, MS:on', 'IS:on, MS:on') );
EMPHASIS_VALUES: array[0..3] of string = ( 'None', '50/15ms','resrerved','CCIT J.17' );
GENRES: array[0..125] of string = ( 'Blues','Classic Rock','Country','Dance','Disco','Funk','Grunge','Hip-Hop','Jazz','Metal', 'New Age','Oldies','Other','Pop','R&B','Rap','Reggae','Rock','Techno','Industrial', 'Alternative','Ska','Death Metal','Pranks','Soundtrack','Euro-Techno','Ambient','Trip-Hop','Vocal','Jazz+Funk', 'Fusion','Trance','Classical','Instrumental','Acid','House','Game','Sound Clip','Gospel','Noise', 'Altern Rock','Bass','Soul','Punk','Space','Meditative','Instrumental Pop','Instrumental Rock','Ethnic','Gothic', 'Darkwave','Techno-Industrial','Electric','Pop-Folk','Eurodance','Dream','Southern Rock','Comedy','Cult','Gangsta', 'Top 40','Christian Rap','Pop/Funk','Jungle','Native American','Cabaret','New Wave','Psychadelic','Rave','Showtunes', 'Trailer','Lo-Fi','Tribal','Acid Punk','Acid Jazz','Polka','Retro','Musical','Rock & Roll','Hard Rock', 'Folk','Folk-Rock','National Folk','Swing','Fast Fusion','Bebob','Latin','Revival','Celtic','Bluegrass', 'Avantgarde','Gothic Rock','Progressive Rock','Psychadelic Rock','Symphonic Rock','Slow Rock','Big Band','Chorus','Easy Listening','Acoustic', 'Humor','Speech','Chanson','Opera','Chamber Music','Sonata','Symphony','Booty Brass','Primus','Porn Groove', 'Satire','Slow Jam','Club','Tango','Samba','Folklore','Ballad','Power Ballad','Rhytmic Soul','Freestyle', 'Duet','Punk Rock','Drum Solo','A Capella','Euro-House','Dance Hall' ); procedure mp3Info(filename:string; var mpeginfo:Tmpeginfo; var ID3v2Tag: TID3v2Tag; var id3v1tag:Tid3v1tag);
implementation
function GetFramelength(layer:byte;bitrate:integer;Samplerate:integer;padding:byte):integer; overload; var framelength:integer; begin if samplerate=0 then framelength := -2 else if Layer=1 then framelength := 12*bitrate*1000 DIV samplerate+padding*4 else framelength := 144*bitrate*1000 DIV samplerate+padding; result := framelength; end;
function GetFramelength(Header:TMPEGHeader):integer; overload; var mpeginfo:Tmpeginfo; framelength:integer; bitrate,version,samplerate:integer; layer:integer; bitrateindex,padding,samplerateindex: byte; begin if (header[1]=$FF) AND (header[2]>=$E0)then begin case ((header[2] shr 3) and 3) of 0: version := 3; 1: version := 0; 2: version := 2; 3: version := 1; end; Layer := 4-((header[2] shr 1) and 3); bitrateindex := (header[3] shr 4) AND $F; bitrate := MPEG_BIT_RATES[version][layer][bitrateindex]; padding := (header[3] shr 1) AND 1; samplerateindex := (header[3] shr 2) AND 3; samplerate := sample_rates[version][samplerateindex]; if samplerate=0 then framelength := -2 else if Layer=1 then framelength := 12*bitrate*1000 DIV samplerate+padding*4 else framelength := 144*bitrate*1000 DIV samplerate+padding; end else begin framelength := -1; end; result := framelength; end;
function ReadToString(buffer: TBuffer; start:integer; Art:byte; alength: integer):string; var tmp:string; tmpws:Widestring; begin if alength<0 then begin result:=''; exit; end; case Art of 0:begin setlength(tmp,alength); move(buffer[start], tmp[1], alength); end; 1: begin setlength(tmpws,alength DIV 2 - 1); move(buffer[start+2], tmpws[1], 2*length(tmpws)); tmp := UTF8ToAnsi(UTF8Encode(tmpws)); end; 2: begin setlength(tmpws,alength DIV 2); move(buffer[start], tmpws[1], 2*length(tmpws)); tmp := UTF8ToAnsi(UTF8Encode(tmpws)); end; 3: begin setlength(tmp,alength); move(buffer[start], tmp[1], alength); tmp:=UTF8ToAnsi(tmp); end; else tmp:=''; end; result:=trim(tmp); end;
procedure mp3Info(filename:string; var mpeginfo:Tmpeginfo; var ID3v2Tag: TID3v2Tag; var id3v1tag:Tid3v1tag); var F: File; id3v1_tag:array[1..128] of char; mp3_header: TMPEGHeader; buffer: TBuffer; fsize:longint; i:integer; id3v1_size:integer; xing_header_size:integer;
id3_version, id3_number,id3_flags:byte; id3_unsync,id3_extended,id3_footer:boolean; id3_frame_id:string[4]; id3_pos:integer; id3_size,id3_extended_size,id3_frame_size:longint;
bitrateindex, versionindex: byte; valid:boolean; position:integer; padding,samplerateindex:byte; framelength:longint; neueframelength:longint; Xing_Offset:integer; Xing_Flags:byte; begin xing_header_size:=0; AssignFile(F, filename); FileMode := 0; Reset(F,1); fsize := filesize(f); MPeginfo.dateigroesse:=fsize;
if fsize=0 then begin CloseFile(F); mpeginfo.position:=-1; exit; end;
if fsize>=6000 then setlength(buffer,6000) else setlength(buffer,fsize); blockread(f,buffer[0],length(buffer)); Seek(F,FileSize(F)-128); BlockRead(F, id3v1_tag, 128); CloseFile(F); position:=-1;
id3v1tag.exists:=false; if (id3v1_tag[1]='T') AND (id3v1_tag[2]='A') AND (id3v1_tag[3]='G') then begin id3v1tag.exists:=true; id3v1tag.id := 'TAG'; id3v1_size := 128; id3v1tag.Titel := trim(copy(id3v1_tag,4,30)); id3v1tag.Artist := trim(copy(id3v1_tag,34,30)); id3v1tag.Album := trim(copy(id3v1_tag,64,30)); id3v1tag.Year := trim(copy(id3v1_tag,94,4)); if ord(id3v1_tag[126])=0 then begin id3v1tag.Comment :=trim(copy(id3v1_tag,98,28)); id3v1tag.Track := ord(id3v1_tag[127]); end else begin id3v1tag.Comment := trim(copy(id3v1_tag,98,30)); id3v1tag.Track := 0; end; id3v1tag.Genre := ord(id3v1_tag[128]); end;
id3v2tag.exists:=False; if (buffer[0]=$49) AND (buffer[1]=$44) AND (buffer[2]=$33) then begin id3v2tag.exists := True; id3_version := buffer[3]; id3_number := buffer[4]; id3_flags := buffer[5]; id3_unsync := ((id3_flags shr 7) AND 1)=1; id3_extended := ((id3_flags shr 6) AND 1)=1; id3_footer := ((id3_flags shr 4) AND 1)=1; id3_size := 2097152 * buffer[6] + 16384 * buffer[7] + 128 * buffer[8] + buffer[9] + 10; if id3_footer then inc(id3_size,10);
if id3_size+3000>length(buffer) then begin Reset(F,1); if fsize>=id3_size+3000 then setlength(buffer,id3_size+3000) else setlength(buffer,fsize); blockread(f,buffer[0],length(buffer)); CloseFile(F); end;
if id3_extended then begin id3_extended_size := 2097152 * buffer[10] + 16384 * buffer[11] + 128 * buffer[12] + buffer[13]; end else id3_extended_size := 0; position := id3_size-1; id3_pos:=10+id3_extended_size; if id3_version=$02 then while (id3_pos<position) do begin id3_frame_id := chr(buffer[id3_pos]) + chr(buffer[id3_pos+1]) + chr(buffer[id3_pos+2]); id3_frame_size := 16384 *buffer[id3_pos+3] + 128 * buffer[id3_pos+4] + buffer[id3_pos+5] + 6; if id3_frame_id='TAL' then id3v2Tag.album := ReadToString(buffer, id3_pos+7, byte(buffer[id3_pos+6]), id3_frame_size-7); if id3_frame_id='TT2' then id3v2Tag.titel := ReadToString(buffer, id3_pos+7, byte(buffer[id3_pos+6]), id3_frame_size-7); if id3_frame_id='TP1' then id3v2Tag.Artist := ReadToString(buffer, id3_pos+7, byte(buffer[id3_pos+6]), id3_frame_size-7); inc(id3_pos,id3_frame_size); end else while (id3_pos<position) do begin id3_frame_id := chr(buffer[id3_pos]) + chr(buffer[id3_pos+1]) + chr(buffer[id3_pos+2]) + chr(buffer[id3_pos+3]); id3_frame_size := 2097152 * buffer[id3_pos+4] + 16384 * buffer[id3_pos+5] + 128 * buffer[id3_pos+6] + buffer[id3_pos+7] + 10; if id3_frame_id='TALB' then id3v2Tag.album := ReadToString(buffer, id3_pos+11, byte(buffer[id3_pos+10]), id3_frame_size-11); if id3_frame_id='TIT2' then id3v2Tag.titel := ReadToString(buffer, id3_pos+11, byte(buffer[id3_pos+10]), id3_frame_size-11); if id3_frame_id='TPE1' then id3v2Tag.Artist := ReadToString(buffer, id3_pos+11, byte(buffer[id3_pos+10]), id3_frame_size-11); inc(id3_pos,id3_frame_size); end; end else id3_size := 0;
valid:=false; mpeginfo.position:=-1; position:=id3_size-1; while NOT ((valid) or (position>length(buffer)+4)) do begin inc(position); if (buffer[position]=$FF) AND (buffer[position+1]>=$E0) then begin valid := true; Versionindex := (buffer[position+1] shr 3) and 3; case versionindex of 0: mpeginfo.version := 3; 1: mpeginfo.version := 0; 2: mpeginfo.version := 2; 3: mpeginfo.version := 1; end; mpeginfo.Layer := 4-((buffer[position+1] shr 1) and 3); mpeginfo.protection := (buffer[position+1] AND 1)=0;
bitrateindex := (buffer[position+2] shr 4) AND $F; mpeginfo.bitrate := MPEG_BIT_RATES[mpeginfo.version][mpeginfo.layer][bitrateindex]; if bitrateindex=$F then valid := false; samplerateindex := (buffer[position+2] shr 2) AND 3; mpeginfo.samplerate := sample_rates[mpeginfo.version][samplerateindex]; padding := (buffer[position+2] shr 1) AND 1;
mpeginfo.channelmode := ((buffer[position+3] shr 6) AND 3); mpeginfo.extension := ((buffer[position+3] shr 4) AND 3); mpeginfo.copyright := ((buffer[position+3] shr 3) AND 1)=1; mpeginfo.original := ((buffer[position+3] shr 2) AND 1)=1; mpeginfo.emphasis := (buffer[position+3] AND 3);
if mpeginfo.layer=2 then begin if (mpeginfo.bitrate=32) AND (mpeginfo.channelmode<>3) then valid := false; if (mpeginfo.bitrate=48) AND (mpeginfo.channelmode<>3) then valid := false; if (mpeginfo.bitrate=56) AND (mpeginfo.channelmode<>3) then valid := false; if (mpeginfo.bitrate=80) AND (mpeginfo.channelmode<>3) then valid := false; if (mpeginfo.bitrate=224) AND (mpeginfo.channelmode=3) then valid := false; if (mpeginfo.bitrate=256) AND (mpeginfo.channelmode=3) then valid := false; if (mpeginfo.bitrate=320) AND (mpeginfo.channelmode=3) then valid := false; if (mpeginfo.bitrate=384) AND (mpeginfo.channelmode=3) then valid := false; end;
framelength:=GetFramelength(mpeginfo.layer, mpeginfo.bitrate, mpeginfo.Samplerate, padding); if framelength<=0 then valid := false;
if mpeginfo.version=1 then if mpeginfo.channelmode<>3 then xing_offset := 32+4 else xing_offset := 17+4 else if mpeginfo.channelmode<>3 then xing_offset := 17+4 else xing_offset := 9+4; if (buffer[position+xing_offset]=$58) AND (buffer[position+xing_offset+1]=$69) AND (buffer[position+xing_offset+2]=$6E) AND (buffer[position+xing_offset+3]=$67) then begin Xing_flags := buffer[position+xing_offset+7]; if (Xing_flags AND 1)=1 then begin mpeginfo.frames := 16777216 * buffer[position+xing_offset+8] + 65536 * buffer[position+xing_offset+9] + 256 * buffer[position+xing_offset+10] + buffer[position+xing_offset+11]; end else mpeginfo.frames := 0; xing_header_size := framelength; try mpeginfo.bitrate := trunc((mpeginfo.samplerate/1000*(fsize-id3_size-id3v1_size-xing_header_size))/(mpeginfo.frames*144)); except valid := false; end; mpeginfo.vbr := true; end else begin try mpeginfo.frames := trunc((fsize-id3_size-id3v1_size-xing_header_size)/framelength); except valid := false; end; mpeginfo.vbr := false; xing_header_size := 0; end;
if (position+framelength>length(buffer)-4) AND (position+framelength+4<fsize) then begin Reset(F,1); Seek(F,position+framelength); blockread(f,mp3_header,4); CloseFile(F); end else begin try mp3_header[1] := buffer[position+framelength]; mp3_header[2] := buffer[position+framelength+1]; mp3_header[3] := buffer[position+framelength+2]; mp3_header[4] := buffer[position+framelength+3]; except mp3_header[1] := 0; mp3_header[2] := 0; mp3_header[3] := 0; mp3_header[4] := 0; end; end; if (mp3_header[1]<>$FF) or (mp3_header[2]<$E0) then valid:=false;
neueframelength := GetFramelength(mp3_header); if neueframelength<=0 then valid:=false else if (position+framelength+neueframelength>length(buffer)-2) AND (position+framelength+neueframelength+4<fsize) then begin Reset(F,1); Seek(F,position+framelength+neueframelength); blockread(f,mp3_header,4); CloseFile(F); end else begin try mp3_header[1] := buffer[position+framelength+neueframelength]; mp3_header[2] := buffer[position+framelength+neueframelength+1]; except mp3_header[1] := 0; mp3_header[2] := 0; end; end; if (mp3_header[1]<>$FF) or (mp3_header[2]<$E0) then valid:=false;
if valid then begin try mpeginfo.dauer := ((fsize-id3_size-id3v1_size-xing_header_size)*8) div ((mpeginfo.bitrate)*1000); except valid := false; end; mpeginfo.position := position; end; end; end; end;
end. |
schreib mal ein kleines anwendungsbeispiel plz 
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 480
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Sa 06.08.05 18:26
Absolutes Minimal-Beispiel: Form mit einer Memo, einem Edit, einem Button.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| procedure TForm1.Button1Click(Sender: TObject); var mpegInfo:TMpegInfo; ID3v1Tag: TID3v1Tag; ID3v2Tag: TID3v2Tag; begin mpegInfo := TmpegInfo.Create; ID3v1Tag := TID3v1Tag.Create; ID3v2Tag := TID3v2Tag.Create; mp3Info(Edit1.Text,mpeginfo,ID3v2Tag,id3v1tag); memo1.lines.add(ID3v1Tag.Artist + ' - ' + id3v1Tag.Titel); mpegInfo.free; ID3v1Tag.free; ID3v2Tag.Free; end; | Besser wäre es z.B. wenn man eine weitere Klasse TMp3File oder so definiert, die dann aus den teilweise recht technischen Informationen die wichtigen herausfiltert. Um sie z.B. in einem Treeview oder so anzuzeigen. Z.B.
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| if ID3v2Tag.exists then myMp3File.Artist := ID3v2Tag.artist else if ID3v1Tag.exists then myMp3File.Artist := ID3v1Tag.artist else myMp3File.Artist := 'Unknown Artist' |
Fehler exists ist jetzt auch behoben.
_________________ We are, we were and will not be.
|
|
F34r0fTh3D4rk
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: So 07.08.05 12:34
das beispiel reicht mir, danke
@ exists: s.o.
bei mir geht's nur so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| var Song: string; mpegInfo: TMpegInfo; ID3v1Tag: TID3v1Tag; ID3v2Tag: TID3v2Tag; begin mp3Info(Filename, mpeginfo, ID3v2Tag, ID3v1Tag); Song := ID3v1Tag.Artist + ' - ' + ID3v1Tag.Titel; end; |
etwas langsamer als die andere prozedur, aber dafür ja auch besser 
|
|
adler
      
Beiträge: 511
Windows XP
Delphi 05 Pers
|
Verfasst: Sa 29.04.06 15:25
Hey!
Ma so ne Frage, wo kommt das mp3info her?
Da sagt er mir ist nicht deklariert, ja wo auch 
_________________ Wo's nix zu gucken gibt, gibts vielleicht was zu hören.
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 480
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Sa 29.04.06 18:14
Mp3Info ist sie eine der langen Prozeduren aus den anderen Postings. Es handelt sich dabei um eine Vorgängerversion von meinen MP3FileUtils. Ein Anwendungsbeispiel liegt dabei. Alternativ kann ich auch diesen FAQ-Beitrag empfehlen.
_________________ We are, we were and will not be.
|
|
adler
      
Beiträge: 511
Windows XP
Delphi 05 Pers
|
Verfasst: So 30.04.06 13:08
Ja ich sehs, mit der Demo, aber er gibt mir keine Werte.
Reicht es eigentlich nicht, wenn ich nur so eine Tid3v1 erstelle, dort loadfromfile und dann die tags auslese?
Weil dann sind die Strings immer leer
_________________ Wo's nix zu gucken gibt, gibts vielleicht was zu hören.
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 480
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: So 30.04.06 13:11
Wenn die Strings leer sind, dann könnte das daran liegen, dass kein ID3v1-Tag vorhanden ist, sondern nur der v2-Tag. Diese sind vom Aufbau her vollkommen verschieden und zueinander inkompatibel.
Prinzipiell reicht es aber, nur den ID3v1-Teil aus der Unit zu nehmen. Nur hat man dann halt nur den v1-tag, nicht den in der Version 2.
Was sagen denn andere Programme (z.B. Winamp) zu den Tags?
_________________ We are, we were and will not be.
|
|
adler
      
Beiträge: 511
Windows XP
Delphi 05 Pers
|
Verfasst: So 30.04.06 13:27
Hehe, danke, ich hab irgendwie immer ein Lied erwischt, wo er auch bei TagExists False zurück gibt.
Bei manchen gehts
Lese jetzt beide aus, kann es sein das es MP3s gibts, die beides nicht haben?
_________________ Wo's nix zu gucken gibt, gibts vielleicht was zu hören.
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 480
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: So 30.04.06 13:44
Natürlich. Der ID3v1-Tag ist ein 128Byte großer optionaler Bereich am Ende der Datei, der einige Textinformationen speichern kann.
Der ID3v2-Tag ist ein optionaler Bereich am Anfang (meistens) der Datei, der afaik bis zu 256MB groß sein kann und beliebige Informationen speichern kann: Texte, Bilder, Videos, sogar andere mp3-Dateien (die wiederrum einen ID3v2-Tag haben können - rekursiv aufgebaute mp3s sind somit möglich  )
Weder das eine noch das andere muss vorhanden sein.
_________________ We are, we were and will not be.
|
|
Heiko
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: So 30.04.06 19:09
adler hat folgendes geschrieben: | | kann es sein das es MP3s gibts, die beides nicht haben? |
| Zitat: | | The audio format MPEG layer I, layer II and layer III (MP3) has no native way of saving information about the contents, except for some simple yes/no parameters like "private", "copyrighted" and "original home" (meaning this is the original file and not a copy). A solution to this problem was introduced with the program "Studio3" by Eric Kemp alias NamkraD in 1996. By adding a small chunk of extra data in the end of the file one could get the MP3 file to carry information about the audio and not just the audio itself. |
Ich glaube das beantwortet alles  . (Quelle: www.id3.org)
|
|
|