如何获取 iPhone 中音频文件的详细信息

2023-11-27

我使用 AVAudioPlayer 制作了自定义播放器。现在,我想获取添加在资源文件夹中的音频文件的详细信息,例如艺术家姓名、专辑名称等。

MPMusicPlayer 提供了用于获取详细信息的 API,但它使用 iPod 库并且不从应用程序的沙箱中获取资源。因此,MPMusicPlayer 在这种情况下不起作用。

那么,我们如何获取iPhone中音频文件的详细信息呢?


您可以通过以下方式获取此信息AudioToolbox.framework. The AudioToolbox.framework是一个 C API,所以我为它编写了一个 Objective-C 包装器:

ID3标签.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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何获取 iPhone 中音频文件的详细信息 的相关文章

  • 如何确定iPhone铃声的当前级别?

    我正在使用 AVSystemController 将 iPhone 铃声静音 但我不知道如何确定铃声的当前级别 有任何想法吗 PS 是的 我知道使用 AVSystemController 可能会导致应用程序被 App Store 禁止 这不
  • 用 UIView 像翻书一样翻页?

    我正在尝试在之间切换UIViews让它看起来就像你正在翻书的一页 The UIViewAnimationTransitionCurlUp如果我能让它向左或向右卷曲 那就非常接近了 这可能吗 我尝试过使用CATRansition但没有一种动画
  • UIView 子类不会自动调整大小

    我一直在寻找有关调整大小的背景信息 但找不到太多 我知道我需要设置autoresizesSubviews在超级视图和autoresizingMask在子视图上 我已经这样做了 并且我的 UIImageViews 正确调整了大小 但我的自定义
  • 避免“在此块中强烈捕获自身可能会导致保留周期”消息

    每次我必须在块内使用全局变量或属性时 如下所示 self save if isItSaving NO self saveMyFile 我必须像这样重写 BOOL iis isItSaving id myself self self save
  • Objective C UIImagePNGRepresentation内存问题(使用ARC)

    我有一个基于 ARC 的应用程序 它从 Web 服务加载大约 2 000 个相当大 1 4MB 的 Base64 编码图像 它将 Base64 解码后的字符串转换为 png图像文件并将其保存到磁盘 这一切都是在一个循环中完成的 我不应该有任
  • 重置转换后的 UIView 的原点会变得疯狂

    我使用 UIView transform 旋转 缩放 UIVIew 效果很好 然而 一旦我更改视图的框架原点 即使我没有执行任何进一步的 CGAffineTransforms 视图的内容也会开始 奇怪 地缩放 为什么会出现这种情况 我该如何
  • Xcode 3.1.4 中内置分析器

    我想知道 Xcode 3 1 4 中内置的分析器是否使得单独使用 LLVM Clang 静态分析器变得多余 请参考这里的原文 使用 LLVM Clang 静态分析器查找内存泄漏 http www fruitstandsoftware com
  • 对于某些纹理尺寸,glFramebufferTexture2D 在 iPhone 上失败

    当我尝试将纹理附加到帧缓冲区时 glCheckFramebufferStatus 报告某些纹理大小的 GL FRAMEBUFFER UNSUPPORTED 我已经在第二代和第四代 iPod Touch 上进行了测试 两个模型之间失败的纹理尺
  • 我什么时候应该对 IBOutlet 使用弱或强限定符? [复制]

    这个问题在这里已经有答案了 可能的重复 ARC 下 IBOutlets 应该强还是弱 https stackoverflow com questions 7678469 should iboutlets be strong or weak
  • 如何更改已上传的 Firebase 存储图像文件名?

    我需要更改已上传到 firebase 存储中的文件名 因为 在 firebase 存储中上传图像后 我将 url 保存在 firebase 数据库中的特定子 文件夹 下 但是 当我将图像移动到另一个子 文件夹 时 我需要根据新名称更改存储中
  • 自定义 MKAnnotationView - 如何捕获触摸而不忽略标注?

    我有一个自定义 MKAnnotationView 子类 它完全按照我想要的方式显示视图 在那个视图中 我有一个按钮 我想捕获按钮上的事件来执行操作 这很好用 但是 我不希望标注被忽略或消失 基本上 触摸标注中的按钮将开始播放声音 但我想保留
  • 使用 Storyboard 时获取 NSManagedObjectContext

    目标是获取当前的 NSManagedObjectContext 以便使用 Core Data 在 iOS 4 3 中 我将 UINavigationController 的委托设置为 AppDelegate 如下所示 在 AppDelega
  • iOS 以编程方式将 AVI 转换为 MP4 格式

    我的应用程序中有一个查询 因为我想将 AVI 格式的视频转换为 MP4 电影格式 所以有没有什么方法可以以编程方式执行此操作 任何代码片段将不胜感激 你需要使用AVAssetExportSession将视频转换为 mp4格式 下面方法转换
  • iPhone UI 带有 Tableview 或 Scrollview? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在 box2d 中停止作用在物体上的力

    我正在 iPhone 上使用 box2d 来创建游戏 我的身体受重力影响向下移动 而不是向右或向左移动 它会被另一个物体击中 然后向右或向左移动 然后我有一个重置按钮 可以将身体移回到起点 唯一的问题是它仍在向右或向左移动 如何抵消球已经行
  • iphone opencv - 模板匹配

    我已经在我的 iphone 项目中实现了这个 OpenCV 构建 http aptogo co uk 2011 09 opencv framework for ios http aptogo co uk 2011 09 opencv fra
  • 删除 UINavigationBar 下的 1px 边框 - 不起作用

    IBOutlet var navBar UINavigationBar self navBar setBackgroundImage UIImage forBarMetrics UIBarMetrics Default self navBa
  • ios 如何存储用户输入的详细信息并取回?

    How to Store用户输入的详细信息和Get it Back在ios中 我有以下关注TextFields UserName Email Re enter Email id Phone State Address Localityand
  • 如何在 xcode 中使用相同的 nib 文件创建多个窗口

    我有一个使用表格视图作为界面的 iPhone 应用程序 每次用户点击其中一个表格单元格时 我想向用户显示另一个窗口 然而 我推入导航控制器的窗口的用户界面非常相似 因此 我决定制作一个 通用 nib 文件 以便在该通用 nib 文件的文件所
  • 在 iPhone 中保存会话数据

    我想将数据存储在应用程序中的不同点 以便应用程序中的对象可以访问这些数据 类似于 php 中的 session 或全局变量 我知道我可以使用 NSUserDefaults 但我不确定如何继续向它添加值然后访问它 例如 首先我想存储登录期间使

随机推荐