Bạn có thể nhận thông tin này qua số AudioToolbox.framework
. Các AudioToolbox.framework
là một C API, vì vậy tôi đã viết một wrapper Objective-C cho nó:
ID3Tag .h:
@interface ID3Tag : NSObject <NSCoding> {
NSString* title_;
NSString* album_;
NSString* artist_;
NSNumber* trackNumber_;
NSNumber* totalTracks_;
NSString* genre_;
NSString* year_;
NSNumber* approxDuration_;
NSString* composer_;
NSString* tempo_;
NSString* keySignature_;
NSString* timeSignature_;
NSString* lyricist_;
NSString* recordedDate_;
NSString* comments_;
NSString* copyright_;
NSString* sourceEncoder_;
NSString* encodingApplication_;
NSString* bitRate_;
NSStream* sourceBitRate_;
NSString* channelLayout_;
NSString* isrc_;
NSString* subtitle_;
}
@property (nonatomic, retain) NSString *title;
@property (nonatomic, retain) NSString *album;
@property (nonatomic, retain) NSString *artist;
@property (nonatomic, retain) NSNumber *trackNumber;
@property (nonatomic, retain) NSNumber *totalTracks;
@property (nonatomic, retain) NSString *genre;
@property (nonatomic, retain) NSString *year;
@property (nonatomic, retain) NSNumber *approxDuration;
@property (nonatomic, retain) NSString *composer;
@property (nonatomic, retain) NSString *tempo;
@property (nonatomic, retain) NSString *keySignature;
@property (nonatomic, retain) NSString *timeSignature;
@property (nonatomic, retain) NSString *lyricist;
@property (nonatomic, retain) NSString *recordedDate;
@property (nonatomic, retain) NSString *comments;
@property (nonatomic, retain) NSString *copyright;
@property (nonatomic, retain) NSString *sourceEncoder;
@property (nonatomic, retain) NSString *encodingApplication;
@property (nonatomic, retain) NSString *bitRate;
@property (nonatomic, retain) NSStream *sourceBitRate;
@property (nonatomic, retain) NSString *channelLayout;
@property (nonatomic, retain) NSString *isrc;
@property (nonatomic, retain) NSString *subtitle;
@end
ID3TagParser.h
#import <Foundation/Foundation.h>
#import "ID3Tag.h"
@interface ID3Parser : NSObject {
}
- (ID3Tag*) parseAudioFileForID3Tag:(NSURL*) url;
@end
ID3TagParser.m
#import "ID3Parser.h"
#import <AudioToolbox/AudioToolbox.h>
@implementation ID3Parser
- (ID3Tag*) parseAudioFileForID3Tag:(NSURL*) url {
if (url == nil) {
return nil;
}
AudioFileID fileID = nil;
OSStatus err = noErr;
err = AudioFileOpenURL((CFURLRef) url, kAudioFileReadPermission, 0, &fileID);
if(err != noErr) {
NSLog(@"AudioFileOpenURL failed");
return nil;
} else {
UInt32 id3DataSize = 0;
char* rawID3Tag = NULL;
// Reads in the raw ID3 tag info
err = AudioFileGetPropertyInfo(fileID, kAudioFilePropertyID3Tag, &id3DataSize, NULL);
if(err != noErr) {
return nil;
}
// Allocate the raw tag data
rawID3Tag = (char *) malloc(id3DataSize);
if(rawID3Tag == NULL) {
return nil;
}
err = AudioFileGetProperty(fileID, kAudioFilePropertyID3Tag, &id3DataSize, rawID3Tag);
if(err != noErr) {
return nil;
}
UInt32 id3TagSize = 0;
UInt32 id3TagSizeLength = 0;
err = AudioFormatGetProperty(kAudioFormatProperty_ID3TagSize, id3DataSize, rawID3Tag, &id3TagSizeLength, &id3TagSize);
if(err != noErr) {
switch(err) {
case kAudioFormatUnspecifiedError:
NSLog(@"err: audio format unspecified error");
return nil;
case kAudioFormatUnsupportedPropertyError:
NSLog(@"err: audio format unsupported property error");
return nil;
case kAudioFormatBadPropertySizeError:
NSLog(@"err: audio format bad property size error");
return nil;
case kAudioFormatBadSpecifierSizeError:
NSLog(@"err: audio format bad specifier size error");
return nil;
case kAudioFormatUnsupportedDataFormatError:
NSLog(@"err: audio format unsupported data format error");
return nil;
case kAudioFormatUnknownFormatError:
NSLog(@"err: audio format unknown format error");
return nil;
default:
NSLog(@"err: some other audio format error");
return nil;
}
}
CFDictionaryRef piDict = nil;
UInt32 piDataSize = sizeof(piDict);
// Populates a CFDictionary with the ID3 tag properties
err = AudioFileGetProperty(fileID, kAudioFilePropertyInfoDictionary, &piDataSize, &piDict);
if(err != noErr) {
NSLog(@"AudioFileGetProperty failed for property info dictionary");
return nil;
}
// Toll free bridge the CFDictionary so that we can interact with it via objc
NSDictionary* nsDict = (NSDictionary*)piDict;
ID3Tag* tag = [[[ID3Tag alloc] init] autorelease];
tag.album = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_Album]];
tag.approxDuration = [NSNumber numberWithInt:[[nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_ApproximateDurationInSeconds]] intValue]];
tag.artist = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_Artist]];
tag.bitRate = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_NominalBitRate]];
tag.channelLayout = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_ChannelLayout]];
tag.comments = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_Comments]];
tag.composer = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_Composer]];
tag.copyright = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_Copyright]];
tag.encodingApplication = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_EncodingApplication]];
tag.genre = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_Genre]];
tag.isrc = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_ISRC]];
tag.keySignature = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_KeySignature]];
tag.lyricist = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_Lyricist]];
tag.recordedDate = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_RecordedDate]];
tag.sourceBitRate = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_SourceBitDepth]];
tag.sourceEncoder = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_SourceEncoder]];
tag.subtitle = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_SubTitle]];
tag.tempo = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_Tempo]];
tag.timeSignature = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_TimeSignature]];
tag.title = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_Title]];
tag.year = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_Year]];
/*
* We're going to parse tracks differently so that we can perform queries on the data. This means we need to look
* for a '/' so that we can seperate out the track from the total tracks on the source compilation (if it's there).
*/
NSString* tracks = [nsDict objectForKey:[NSString stringWithUTF8String: kAFInfoDictionary_TrackNumber]];
int slashLocation = [tracks rangeOfString:@"/"].location;
if (slashLocation == NSNotFound) {
tag.trackNumber = [NSNumber numberWithInt:[tracks intValue]];
} else {
tag.trackNumber = [NSNumber numberWithInt:[[tracks substringToIndex:slashLocation] intValue]];
tag.totalTracks = [NSNumber numberWithInt:[[tracks substringFromIndex:(slashLocation+1 < [tracks length] ? slashLocation+1 : 0)] intValue]];
}
// ALWAYS CLEAN UP!
CFRelease(piDict);
nsDict = nil;
free(rawID3Tag);
return tag;
}
}
@end
đẹp mã! Bạn chỉ cần quên một số dọn dẹp bộ nhớ (quan trọng nhất là 'AudioFileClose'). Tôi chạy mã trên một loạt các tập tin, thông thường các vấn đề bộ nhớ sẽ không là một vấn đề. – newenglander
Tôi có thể nhận được tất cả thông tin của bản nhạc. nhưng không thể có được lời bài hát ... Vì vậy, bất kỳ ý tưởng về lời bài hát ... –
Cảm ơn bạn đã viết mã. – Vignesh