用于音频文件的Delphi库。
从许多不同的音频格式中读取和写入元标记(例如艺术家,标题,专辑,流派,...),并收集有关音频文件的信息(例如持续时间,比特率,采样)。 AudiowerKzeugebibliothek具有非常简单的用法,用于基本信息,但它还包含了几乎所有类型的元数据的强大功能。
支持的标签格式( BOLD:new v3.0中的新):
限制:
属性TTagItem.DataSize 。
添加了URL框架并在TID3v2Tag.GetUnusedTextTags中注释。
方法TOggContainer.ReadPackets(Target: TObjectList)从OggStream获取所有数据包。
属性TOpusFile.VBR (几乎在每种情况下都应该是True ) *
在M4A文件中读取/写入整数原子的方法。注意:谨慎使用。我需要在我的主要项目“ NEMP”中进行“ TMPO”原子(又称BPM,每分钟节拍),但这并未对其他原子进行广泛的测试。那里的文档不是很有帮助,并且有关签名/未签名的整数和值的大小存在一些不一致之处(8、16、24、32位)。
TApeTag.GetUnusedTextTags ttApev2的tagtype ttVorbis
TApeTag.EAN的getter和setter使用了不同的键。
用红衣主教/整数类型修复了oggpages中的连续名单的混乱。
FLAC文件:已删除的删除功能Fisvalid
修复了有关OGGPAGES和OGGPACKET的解析错误(实际上对OGG/Opus文件没有影响,但对新方法ReadPackets没有影响)。
图书馆AudiowerKzeugebibliothek源自MP3,Flag,Ogg等的几个格式特定的库。因此,《法规》中有很多过去的负担。一些重复,参数顺序,类型或命名以及其他一些不便。
使用3.0版,我尝试提高所提供方法的总体一致性和可用性。但是,不可能向下兼容。
有很多更改,您需要在代码中进行相应的更改。
有关一些详细信息,请参见ChangElog。
您可以在不同的“级别”上使用此库,但是这些级别之间没有真正的区别。您可以或多或少地从此库的功能中使用。根据您想做的事情,建议您或多或少了解“音频文件”的内部结构。
TTagItem类的对象。这些对象中有许多包含文本信息,但是图像或其他二进制数据也可以。有关示例,请参见演示项目。
TBaseAudioFile (单位Audiofiles.base.pas):一个抽象类声明一些基本属性,例如标题,艺术家,专辑,持续时间等,然后在以下TxxxFile类中实现。TMP3File , TOggVorbisFile , TFlacFile ,...(单独的单位):几种filetypes的类,这些类别实现了在tbaseaudiofile中声明的抽象方法,并且可以定义更多方法。如果您想要有关文件的更多信息,则可能需要明确访问这些派生类的属性和方法。对于几种包含APEV2-TAGS或VORBIS注释的文件类型,也有一些“中间类”,例如TBaseApeFile或TBaseVorbisFile 。TAudioFileFactory (单位Audiofiles.factory.pas):基于文件扩展程序创建正确的音频文件实例的工厂类。TTagItem (Autioofiles.basetags.pas):元数据容器中所有单个元素的抽象基类。从本质上讲,提供了一个“键”和“值”,并补充了有关数据元素的其他一些信息。源自此的是TID3v2Frame , TApeTagItem , TCommentVector等类。TID3v1Tag , TID3V2Tag , TApeTag , TVorbisComments ...(单独的单位,没有共同祖先):实现单个元数据容器。极为简化:TTAGITEMS列表。 对于初学者来说,该库的使用非常容易。只需使用工厂创建一个类型的TBaseAudioFile对象以显示某些属性,让用户编辑一些值并更新文件。就这样。使用所有受支持的文件格式-MP3,OGG,FLAC,M4A,都无关紧要。所有人的代码相同。
var
MainAudioFile: TBaseAudioFile;
// ...
MainAudioFile := AudioFileFactory.CreateAudioFile(aFileName);
MainAudioFile.ReadFromFile(aFileName);
EditTitle.Text := MainAudioFile.Title;
// ... and for editing the file:
MainAudioFile.Title := EditTitle.Text;
MainAudioFile.UpdateFile;请注意,您不需要创建(或免费)AudiofileFactory-Object。这是由单位AudioFiles.Factory.pas自动处理的。
有关详细信息,请参见演示“ Demosimple”。
重要说明:工厂可能不是线程安全。如果要在辅助线程中使用它,则应在线程的上下文中创建另一个工厂。
如果提供的命名属性(例如艺术家,标题和其他属性还不够,则有Audiiofile.GetTaglist方法(本库的版本3中的新方法)。这使您可以在文件中列出和编辑所有数据元素。
lvMetaTags.Clear; // a ListView on the Form
TagItems := TTagItemList.Create;
try
AudioFile.GetTagList(TagItems);
for i := 0 to TagItems.Count - 1 do begin
newListItem := lvMetaTags.Items.Add;
newListItem.Data := TagItems[i];
newListItem.Caption := cTagTypes[TagItems[i].TagType];
newListItem.SubItems.Add(TagItems[i].Key);
newListItem.SubItems.Add(TagItems[i].Description);
newListItem.SubItems.Add(TagItems[i].GetText(tmReasonable));
end ;
finally
TagItems.Free;
end ;要从此列表中编辑元素,您可以使用以下代码:
editItem := TTagItem(lvMetaTags.Selected.Data);
editValue := editItem.GetText(tmReasonable);
if InputQuery( ' Edit Item ' , ' New value: ' , editValue) then begin
if editValue = ' ' then
AudioFile.DeleteTagItem(editItem)
else
TTagItem(editItem).SetText(editValue, tmReasonable);
end ;虽然音频文件中的大多数元数据都包含文本,但有些数据具有更复杂的结构,甚至包含纯二进制数据。如何识别数据类型因格式而异。可能的类型有时也会更多,有时甚至更少。而且,“文本”也有一些细微之处,尤其是在ID3V2标签上。例如,“歌词”不仅包含文本本身,还包含一些其他数据,例如语言。为此,音频Werkzeuge Bibliothek提供了枚举类型teTagContentType和teTextMode 。 TagContentType提供了有关内容类型的信息。除了几种通常有效的类型( tctText, tctPicture, tctBinary )外,还有各种格式特异性类型,例如用于ID3V2的tctLyrics或tctUserText ,用于M4A文件的APEV2或tctGenre tctExternal对于其中一些类型,即使它们具有不同的内部结构,也应分别处理。为此目的,可以将TextMode参数设置为tmReasonable 。阅读数据时,也可以使用tmForced 。然后,二进制数据也以文本形式显示(不可打印的字符被点替换为“。”)。
AudioFile.GetTagList(TagItems);具有可选参数,您可以在其中定义要包含在Tagitems列表中的哪种标签。
procedure GetTagList(Dest: TTagItemList; ContentTypes: TTagContentTypes = cDefaultTagContentTypes);
默认值将返回可以解释为文本的各种标签,即
cDefaultTagContentTypes = [tctText, tctComment, tctLyrics, tctURL, tctUserText, tctUserURL, tctExternal, tctTrackOrDiskNumber, tctGenre, tctSpecialText];
大多数元数据容器都允许一张以上的图片,也就是“封面艺术”。如果要显示封面艺术,则需要先获取所有图片标签项目的列表。
picList := TTagItemList.Create;
try
AudioFile.GetTagList(picList, [tctPicture]);
if picList.Count > 0 then begin
// show first picture in the list, or try to get the "Front Cover"
// here: Just diplay the first one in the list (which ist often
// the only one)
stream := TMemoryStream.Create;
try
if picList[ 0 ].GetPicture(stream, Mime, PicType, Description)
then begin
Stream.Position := 0 ;
// Modern versions of Delphi also recognize the graphic type when
// using LoadFromStream
// For older versions, you may have to adapt the code depending
// on the mimetype.
Image1.Picture.LoadFromStream(Stream);
end ;
finally
stream.Free;
end ;
end ;
finally
picList.Free;
end ;有关详细信息,请参见演示“删除”。
在专家级别上,您不再使用经常使用的基本类TBaseAudioFile 。相反,您可以直接与派生的类和特定的元数据容器一起工作。
由于这为您提供了对文件及其内部结构的非常基本的访问,因此您也可以对它们做很多胡说八道,这可能会导致其他程序问题。之所以这样做,是因为您不遵守已记录的标准,或者因为您打破了普遍认可的非官方规则。在OGG文件中编写ID3V2标签是可能的,但肯定不是一个好主意。也没有将Vorbis评论写入MP3文件。
使用谨慎提供的选项 - 尤其是在写入访问时。
有关可能的更多详细信息,请参见Demo“ Demomp3”(但并非总是推荐的,有些玩家可能会对这些文件偶然发现)。
几种音频格式可能包含文件中的不同类型的元数据。该库使用以下假设
MP3文件通常包含ID3V1和ID3V2标签。使用类TMP3File时,通常可以确保两个版本在文件中保持一致。
MP3文件有时还包含APEV2-TAG。现在,该标签也通过类TMP3File完全处理。设置基本属性将确保所有元标记保持一致。确保属性TagsToBeWritten包含mt_Existing (这是默认值)。
Vorbis评论和APEV2标签中没有定义“歌词”的标准密钥。根据我的研究,正在使用以下变体: UNSYNCEDLYRICS , UNSYNCED LYRICS (带有空间)和LYRICS 。阅读“歌词”时,考虑了这三个键。写作时,使用现有密钥。如果三个变体都没有可用,则使用全局变量AWB_DefaultLyricsKey中的密钥集。默认值是UNSYNCEDLYRICS 。
默认情况下,使用APEV2标签(Monkey,Wavpack,Musepack,Optimfrog,Trueaudio)使用所有音频格式也可能包含ID3V1-和ID3V2标签。这些格式的TxxxFile类现在确实完全处理ID3V1-TAG。检测到ID3V2-TAG的存在(如果需要的话,则考虑在持续时间的计算中进行的大小),但否则被忽略了。
对于MP3文件和基于APE的文件,您可以使用属性TagsToBeWritten , TagsToBeDeleted和DefaultTags来确定使用方法UpdateFile或RemoveFile或RemoveFromFile时,将哪些元标记写入/从文件中写入/删除。默认设置是
// for mp3 files
TagsToBeWritten := [mt_Existing];
DefaultTags := [mt_ID3v1, mt_ID3v2]; // **
TagsToBeDeleted := [mt_Existing];
// for ApeV2-based file formats
TagsToBeWritten := [mt_Existing];
DefaultTags := [mt_ID3v1, mt_APE]; // **
TagsToBeDeleted := [mt_Existing];
// ** used when there are no meta tags at all如果您正在扫描多个文件中的元数据(例如将数据存储到媒体库中),则可能只需“标题”,但是您不在乎它是来自ID3V2-还是ID3V1-TAG。为了加快扫描速度(至少这是希望),引入了属性TagScanMode 。可能的值是
TTagScanMode = (id3_read_complete, id3_read_smart, id3_read_v2_only );默认值是id3_read_complete ,其中所有包含的标签都已处理。选项id3_read_smart将首先检查ID3V2-TAG。此元标记更复杂,但是无论如何都需要阅读以获取诸如比特率,持续时间和其他内容之类的音频元数据。在智能模式下,只有从文件中读取ID3V1-TAG,如果没有适当的ID3V2-TAG包含艺术家,标题,专辑,曲目,曲目,年和流派的情况。如果您还希望包含“注释”字段,请将fSmartRead_IgnoreComment设置为False 。
如果您通过类TMP3File的设置更改这些属性之一,则属性fSmartRead_AvoidInconsistentData (默认值: True )将确保还可以正确处理ID3V1-TAG,因此UpdateFile将同时编写ID3V1-和ID3V2-TAG,并使用一致的数据(根据TagWriteMode的设置)。
注意:对于基于APE的文件,这不需要。检测APE标签始终也需要检查(和读取)ID3V1标签,因此没有显着的加速。
通常,用可变比特率编码的MP3文件包含一个所谓的Xing-header(或类似的内容),其中包含快速计算文件持续时间所需的其他数据。最近,我发现了一些没有这样的Xing头标头的文件,导致计算的持续时间更长,比特率太低(即32 kbit/s)。这不是这个库的问题,但仍然适用于许多其他图书馆。
对于此类文件,引入了新的属性TMP3File.MpegScanMode 。可能的值是
TMpegScanMode = (MPEG_SCAN_Fast, MPEG_SCAN_Smart, MPEG_SCAN_Complete);MPEG_SCAN_Fast与以前一样扫描文件,诚实地说,VBR文件包含一个Xing-header(或类似的内容)。在大多数情况下,这效果很好。MPEG_SCAN_Smart检查快速扫描的结果是否确实有意义。如果计算出的比特率为32 kbit/s(甚至较低,实际上是无效的),则可能出现问题。因此,该文件已完全处理,扫描每个MPEG框架。请注意,大多数mp3文件都以稍微沉默的一刻开始。设置为“ VBR”的编码器可能会使用最小可能的空间来编码此空间 - 为32kbit/s。MPEG_SCAN_Complete始终不使用完整的文件。这导致最准确的持续时间,但还需要更多的时间。默认模式是MPEG_SCAN_Smart 。
该库应与Delphi 7到Delphi 12的所有Delphi版本一起使用。但是,在没有内置Unicode支持的情况下,有一些事情要记住较旧的版本(= Delphi 2009之前)。
注意:我在这里使用“ Unicode”的含义“超过ANSI”。这不是100%准确的,但我希望您知道我在说什么。 ;-)
在Delphi 2009年之前,VCL仅为ANSI,不支持Unicode。这包括显示带有Unicode字符的字符串,并在其文件名中打开带有Unicode字符的文件。为此,有一系列称为“ tntunicodecontrols”的组件。该系列的较旧版本可在创意共享许可下获得,并且仍应在某个地方找到。
该库可以通过激活文件config.inc中的编译器开关来利用这些控件。只需删除“。”在行{.$DEFINE USE_TNT_COMPOS}中。
在库中,TNT用于类TNTFileStream 。当然,您也可以使用其他功能Unicode的Filestream类。只需根据您的需要调整这些代码行:(文件:Audiofiles.declarations.pas)
{ $IFDEF USE_TNT_COMPOS }
TAudioFileStream = TTNTFileStream;
{ $ELSE }
TAudioFileStream = TFileStream;
{ $ENDIF }如果您使用的是没有Tntunicodecontrols的旧版本,则该库仍然可以使用,但是您无法使用“จักรพรรณ์ -10เท่านี้ก็ตรม。Mp3”之类的文件名打开文件。当您尝试从此类文件中显示有关标题和艺术家的信息(重命名后)时,您只会看到一些“ ?????”而不是实际标题。请注意,在这种情况下重写元标记可能会导致数据丢失。
注意:示例项目不使用TNTControls(例如TTNTEDIT而不是TEDIT)。小心旧的德尔菲斯。 ;-)
较新的Delphi版本(2009年及以后)具有内置的Unicode支持,因此不需要使用这些Tntunicodecontrols。此外,那里不需要UnicodeString的定义。这就是该编译器开关的原因:
{$IFNDEF UNICODE}
UnicodeString = WideString;
{$ENDIF}
在此库的2.0版中,我为不同类型的有声副词使用了出厂模式。特定音频文件格式的类在工厂类中注册。为了管理所有注册类,工厂类默认使用TDICTIONARY。如果您的Delphi版本不支持Tdictionary,请在confic.inc中使用它的用法。在这种情况下,将使用常规的托管清单。
{$DEFINE USE_DICTIONARY}
为了提高TobjectList的访问速度,它使用“转管方法”将其实现为自组织列表。如果通过工厂创建带有特定文件名扩展名的音频文件,则该扩展名/类将在列表中向上移动,从而减少了再次找到它的时间。
在大多数情况下,该库应正确读取各种音频文件的信息。但是,使用该库未正确处理的方法或变体“在野外”中有一些奇怪的音频文件。我认为,经过几年的时间,我现在几乎要应对所有内容,但是仍然可能会缺少一些难得的情况。
如果您发现一个错误,或者有一些音频文件(尤其是mp3文件!),该库的方法提供了错误的数据,请与我联系和/或将一些示例文件发送到[email protected]。
但是我不能(也不会)修复所有问题。我见过的最疯狂的事情是一个ID3V2TAG,其中包含以下编码:UTF-16(fine),无效终止(或多或少的标准),从BOM(OK ...)开始,逐个字符(wtf ...?) - 是的,是的。每个字符总共6个字节...