Uma biblioteca Delphi para arquivos de áudio.
Leia e escreva meta tags (como artista, título, álbum, gênero, ...) de muitos formatos de áudio diferentes e colete informações sobre o arquivo de áudio (como duração, taxa de bits, amostrador). O AudiowerkzeugeBibliothek vem com um uso muito simples para informações básicas, mas também contém recursos poderosos para um acesso profundo a quase todo tipo de meta-dados.
Formatos de tags suportados ( negrito: novo em v3.0 ):
Limitações:
Propriedade TTagItem.DataSize .
Adicionado quadros de URL e comentar ao TID3v2Tag.GetUnusedTextTags .
Método TOggContainer.ReadPackets(Target: TObjectList) para obter todos os pacotes do OggStream.
Propriedade TOpusFile.VBR (que deve ser True em quase todos os casos) *
Métodos para ler/gravar átomos inteiros nos arquivos M4A. Nota: Use com cautela. Eu preciso disso no meu projeto principal "NEMP" para o átomo "TMPO" (também conhecido como BPM, batidas por minuto), mas isso não é amplamente testado para outros átomos. A documentação não é muito útil e há algumas inconsistências em relação a números inteiros assinados/não assinados e o tamanho dos valores (8, 16, 24, 32 bits).
Tagtype em TApeTag.GetUnusedTextTags foi ttVorbis , correto é ttApev2 .
Getter e setter para TApeTag.EAN usavam teclas diferentes.
Corrigido a desordem com o tipo cardeal/número inteiro para serialNumber em OgGPages.
Arquivos FLAC: função depreciada excluída fisvalid
Corrigido um erro de análise em relação a OgGPages e OgGPackets (que na verdade não tiveram efeito nos arquivos OGG/OPUS, mas no novo método readpackets).
A biblioteca AudiowerKzeugeBibliothek se originou de várias bibliotecas específicas de formato para MP3, Flag, Ogg e outros. Por causa disso, havia muito fardo do passado contido no código. Algumas duplicatas, nenhuma consistência na ordem dos parâmetros, tipo ou nomeação e alguns outros inconvenientes.
Com a versão 3.0, tento melhorar a consistência geral e a usabilidade dos métodos fornecidos. No entanto, não é possível fazer isso compatível descendente.
Existem muitas, muitas alterações, e você precisará fazer alterações correspondentes em seu código.
Veja Changelog para obter alguns detalhes.
Você pode usar essa biblioteca em diferentes "níveis", mas não há uma diferenciação real entre esses níveis. Você pode usar mais ou menos com os recursos desta biblioteca. Dependendo do que você deseja fazer, é recomendável saber mais ou menos sobre a estrutura interna dos "arquivos de áudio".
TTagItem . Muitos desses objetos contêm informações de texto, mas imagens ou outros dados binários também são possíveis.Veja os projetos de demonstração para exemplos.
TBaseAudioFile (unidade audiofiles.base.pas): uma classe abstrata que declara algumas propriedades básicas como título, artista, álbum, duração e outros, que são implementados nas seguintes classes TxxxFile .TMP3File , TOggVorbisFile , TFlacFile , ... (unidades separadas): classes para os vários filetipos, que implementam os métodos abstratos declarados em tbaseaudiofile e podem definir mais alguns métodos. Se você deseja mais informações sobre um arquivo, pode ser necessário acessar explicitamente as propriedades e métodos dessas classes derivadas. Existem também algumas "classes intermediárias" como TBaseApeFile ou TBaseVorbisFile para vários tipos de arquivos que contêm comentários APEV2-TAGS ou VORBIS.TAudioFileFactory (Unit Audiofiles.Factory.PAs): A classe de fábrica para criar as instâncias corretas do arquivo de áudio com base na extensão do arquivo.TTagItem (unidade Audiofiles.basetags.pas): a classe base abstrata para todos os elementos individuais em um contêiner de metadados. Essencialmente, é fornecida uma "chave" e um "valor", complementadas por algumas outras informações sobre o elemento de dados. Derivados disso são as classes TID3v2Frame , TApeTagItem , TCommentVector e outras.TID3v1Tag , TID3V2Tag , TApeTag , TVorbisComments ... (unidades separadas, nenhum ancestral comum): Implementação dos contêineres de metadados individuais. Extremamente simplificado: uma lista de TTAGItems. Para iniciantes, o uso desta biblioteca é super fácil. Basta usar a fábrica para criar um objeto do tipo TBaseAudioFile para exibir algumas das propriedades, deixe o usuário editar alguns dos valores e atualizar o arquivo. Isso é tudo. Trabalha em todos os formatos de arquivo suportados - MP3, OGG, FLAC, M4A, isso não importa. Mesmo código para todos.
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; Observe que você não precisa criar (ou livre) o AudiofileFactory-Object. Isso é tratado pela unidade AudioFiles.Factory.pas automaticamente.
Veja a demonstração "Demosimple" para obter detalhes.
NOTA IMPORTANTE: A fábrica provavelmente não é segura por threads. Se você deseja usá -lo em um thread secundário, crie outra fábrica no contexto do thread.
Se as propriedades nomeadas fornecidas (como artista, título e outros) não forem suficientes, existe o método Audiofile.GetTaglist (novo na versão 3 desta biblioteca). Isso permite listar e editar todos os elementos de dados em um arquivo.
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 ;Para editar um elemento desta lista, você pode usar o seguinte código:
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 ; Embora a maioria dos metadados nos arquivos de áudio contenha texto, existem alguns dados que possuem uma estrutura mais complexa ou até contém dados binários puros. Como o tipo de dados pode ser reconhecido difere do formato para o formato. Os tipos possíveis também são às vezes mais e às vezes menos diferenciados. E também há algumas sutilezas a serem consideradas com os "textos", especialmente com a tag ID3V2. Lá, por exemplo, "letras" contêm não apenas o texto em si, mas também alguns dados adicionais - por exemplo, o idioma. Para esse fim, o Audio Werkzeuge Bibliothek fornece os tipos de enumeração teTagContentType e teTextMode . O TagContentType fornece informações sobre o tipo de conteúdo. Além de alguns tipos geralmente válidos ( tctText, tctPicture, tctBinary ), existem vários tipos específicos de formato, como tctLyrics ou tctUserText para ID3V2, tctExternal para APEV2 ou tctGenre para arquivos M4A. Para alguns desses tipos, é razoável considerá -los como texto, mesmo que tenham uma estrutura interna diferente e sejam tratados separadamente. O parâmetro TextMode pode ser definido como tmReasonable para esse fim. Ao ler os dados, tmForced também está disponível. Os dados binários também são exibidos em forma de texto (caracteres não impressos são substituídos por pontos ".").
O método AudioFile.GetTagList(TagItems); Possui um parâmetro opcional, onde você pode definir qual tipo de tags você deseja ser incluído na lista TagItems.
procedure GetTagList(Dest: TTagItemList; ContentTypes: TTagContentTypes = cDefaultTagContentTypes);
O valor padrão retornará todos os tipos de tags que podem ser interpretadas como texto, ou seja,
cDefaultTagContentTypes = [tctText, tctComment, tctLyrics, tctURL, tctUserText, tctUserURL, tctExternal, tctTrackOrDiskNumber, tctGenre, tctSpecialText];
A maioria dos contêineres de metadados permite mais de uma foto, também conhecida como "arte da capa". Se você deseja exibir a arte da capa, precisa obter uma lista de todos os itens de tag de imagem primeiro.
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 ;Veja a demonstração "Demoexted" para obter detalhes.
No nível do especialista, você não usa mais a classe TBaseAudioFile que é frequentemente. Em vez disso, você trabalha diretamente com as classes derivadas e os metadados específicos.
Como isso fornece acesso muito básico aos arquivos e sua estrutura interna, você também pode fazer muitas bobagens com eles, o que pode levar a problemas com outros programas. Seja porque você não adere ao padrão documentado ou porque quebra regras não oficiais geralmente reconhecidas. Escrever uma tag ID3V2 em um arquivo OGG é possível, mas certamente não é uma boa ideia. Nem está escrevendo um comentário de Vorbis em um arquivo MP3.
Use as opções fornecidas com cautela - especialmente com acesso a gravação.
Veja a demonstração "Demomp3" para obter mais detalhes do que é possível (mas nem sempre recomendado, alguns jogadores podem tropeçar nesses arquivos).
Vários formatos de áudio podem conter diferentes tipos de meta -dados dentro do arquivo. Esta biblioteca usa as seguintes suposições
Os arquivos MP3 geralmente contêm ID3V1 e ID3V2-TAGS. Ao usar a classe TMP3File , geralmente é garantido que ambas as versões permaneçam consistentes no arquivo.
Os arquivos MP3 às vezes também contêm um APEV2-TAG. Esta tag agora também está totalmente processada pela classe TMP3File . A configuração de propriedades básicas garantirá que todas as metatags permaneçam consistentes. Verifique se a propriedade TagsToBeWritten contém mt_Existing (que é o valor padrão).
Não há chave padrão definida para "letras" nos comentários de Vorbis e nas tags APEV2. De acordo com minha pesquisa, as seguintes variantes estão em uso: UNSYNCEDLYRICS , UNSYNCED LYRICS (com um espaço) e LYRICS . Essas três chaves são levadas em consideração ao ler 'Letras'. Ao escrever, a chave existente é usada. Se nenhuma das três variantes estiver disponível, será usado a chave na variável global AWB_DefaultLyricsKey . O valor padrão é UNSYNCEDLYRICS .
Todos os formatos de áudio usando TAGs APEV2 por padrão (Monkey, Wavpack, Musepack, Optimfrog, Trueaudio) também podem conter ID3V1- e Id3v2-Tags. As classes TxxxFile para esses formatos agora processam totalmente o ID3V1-TAG. A existência de um TAG ID3V2 é detectada (e seu tamanho é considerado para o cálculo da duração, se necessário), mas de outra forma ignorado.
Para arquivos MP3 e arquivos baseados em macacos, você pode usar o TagsToBeWritten , TagsToBeDeleted e DefaultTags para decidir quais tags de meta são escritas/removidas para/do arquivo ao usar o método UpdateFile ou RemoveFromFile . As configurações padrão são
// 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 Se você estiver examinando vários arquivos em busca de dados de meta (por exemplo, para armazenar os dados em uma biblioteca de mídia), você pode querer apenas o "título", mas não se importa se ele vem do ID3V2- ou do ID3V1-TAG. Para acelerar a digitalização (pelo menos essa é a esperança), a propriedade TagScanMode é introduzida. Valores possíveis são
TTagScanMode = (id3_read_complete, id3_read_smart, id3_read_v2_only ); O valor padrão é id3_read_complete , onde todas as tags contidas são processadas. A opção id3_read_smart verificará o ID3V2-TAG primeiro. Esta meta tag é mais complexa, mas precisa ser lida de qualquer maneira para acessar os meta -dados de áudio, como taxa de bits, duração e outras coisas. No modo inteligente, o ID3V1-TAG é lido apenas no arquivo, se não houver artista, título, álbum, faixa, ano e gênero. Se você também deseja o campo "Comentário" incluído, defina fSmartRead_IgnoreComment como False .
Se você alterar uma dessas propriedades através dos setters do classes TMP3File , a propriedade fSmartRead_AvoidInconsistentData (Padrão: True ) garantirá que também o ID3V1-TAG seja processado corretamente, para que o UpdateFile escreva o ID3V1- e o ID3V2-TAG com dados consistentes (de acordo com a configuração da TagWriteMode .
Nota: Para arquivos baseados em macacos, isso não é necessário. A detecção de manchas de macaco sempre exige verificação (e leitura) ID3V1-TAGS também, para que não haja aceleração significativa.
Geralmente, os arquivos MP3 codificados com taxa de bits variáveis contêm um chamado cabeçalho Xing (ou algo semelhante) contendo dados adicionais necessários para um cálculo rápido da duração do arquivo. Recentemente, encontrei alguns arquivos sem um cabeçalho Xing, resultando em durações calculadas muito mais longas e taxas de bits muito baixas (ou seja, 32 kbit/s). Isso não foi um problema apenas para esta biblioteca, mas ainda é para muitas outras bibliotecas.
Para esses arquivos, a nova propriedade TMP3File.MpegScanMode é introduzida. Valores possíveis são
TMpegScanMode = (MPEG_SCAN_Fast, MPEG_SCAN_Smart, MPEG_SCAN_Complete);MPEG_SCAN_Fast Digitaliza o arquivo como antes, de boa fé, que um arquivo VBR contém um cabeçalho Xing (ou algo equivalente). Isso funciona muito bem na maioria dos casos.MPEG_SCAN_Smart verifica se o resultado da varredura rápida faz sentido. Se a taxa de bits calculada for de 32 kbit/s (ou até menor, o que seria realmente inválido), provavelmente há algo errado. Portanto, o arquivo é completamente processado, digitalizando cada quadro MPEG. Observe que a maioria dos arquivos MP3 começa com um pequeno momento de silêncio. Um conjunto de codificadores como "VBR" provavelmente usará a quantidade mínima possível de espaço para codificar isso - que é de 32kbit/s.MPEG_SCAN_Complete sempre sem o arquivo completo. Isso leva às durações mais precisas, mas também exige muito mais tempo. O modo padrão é MPEG_SCAN_Smart .
Esta biblioteca deve funcionar com todas as versões Delphi, do Delphi 7 a Delphi 12 . No entanto, há algumas coisas a serem lembradas com versões mais antigas sem suporte de unicode embutido (= antes de Delphi 2009).
Nota : Eu uso "Unicode" aqui no significado de "mais do que ANSI". Isso não é 100% preciso, mas espero que você saiba o que estou dizendo. ;-)
Antes de Delphi 2009, o VCL era apenas e não apoiava o Unicode. Isso inclui a exibição de strings com caracteres unicode e abrindo arquivos com caracteres Unicode em seus nomes de arquivos. Para isso, tem havido uma coleção de componentes chamados "tntunicodecontrols". As versões mais antigas desta coleção estavam disponíveis sob uma licença Creative Commons e ainda devem ser encontradas em algum lugar.
Esta biblioteca pode usar esses controles ativando um comutador compilador no arquivo config.inc . Basta remover o "". na linha {.$DEFINE USE_TNT_COMPOS} .
Dentro da própria biblioteca, os TNTs são usados para a classe TNTFileStream . Claro que você também pode usar outras classes FileStream capaz de unicode. Basta ajustar essas linhas de código de acordo com suas necessidades: (arquivo: audiofiles.declarations.pas)
{ $IFDEF USE_TNT_COMPOS }
TAudioFileStream = TTNTFileStream;
{ $ELSE }
TAudioFileStream = TFileStream;
{ $ENDIF }Se você estiver usando uma versão Delphi mais antiga sem tntunicodecontrols, esta biblioteca ainda funcionará, mas você não poderá abrir arquivos com nomes de arquivos como "จักรพรรณ์ อาบครบุรี - 10 เท่านี้ก็ตรม. Mp3". Quando você tenta exibir informações sobre o título e o artista desse arquivo (depois de renomeá -lo), você verá apenas alguns "?????" em vez do título real. Observe que a reescrita das meta tags nessas condições pode levar à perda de dados.
NOTA : Os projetos de amostra não usam os TNTControls (como o TTNtedit em vez do TEDIT). Tenha cuidado com Delphis mais antigo. ;-)
As versões Delphi mais recentes (2009 e posterior) têm suporte de unicode embutido e, portanto, o uso desses tnunicodecontrols não é necessário. Além disso, a definição do tipo UnicodeString não é necessária lá. Esta é a razão para este interruptor do compilador:
{$IFNDEF UNICODE}
UnicodeString = WideString;
{$ENDIF}
Na versão 2.0 desta biblioteca, uso um padrão de fábrica para os diferentes tipos de audiofiles. Uma classe para um formato de arquivo de áudio específico é registrado na classe de fábrica. Para gerenciar todas as classes registradas, a classe de fábrica usa um tdictionary por padrão. Se a sua versão Delphi não suportar tdictionary, indefinir seu uso no confic.inc . Nesse caso, um TobBjectList regular será usado para isso.
{$DEFINE USE_DICTIONARY}
Para aumentar a velocidade de acesso no TobjectList, ele é implementado como uma lista de auto-organização, usando o "método de transposição". Se um arquivo de áudio com uma extensão de nome de arquivo específica for criado através da fábrica, essa extensão/classe será movida para cima na lista, reduzindo o tempo para encontrá -lo novamente.
Esta biblioteca deve ler corretamente as informações de todos os tipos de arquivos de áudio na maioria dos casos. No entanto, existem alguns arquivos de áudio ímpares "no Wild", usando métodos ou variantes que não são tratados corretamente por esta biblioteca. Eu acho que, depois dos anos dos severais, estou lidando com quase tudo agora, mas ainda pode haver alguns casos raros que estou perdendo.
Se você encontrou um bug, ou se tiver alguns arquivos de áudio (especialmente arquivos MP3!), Onde os métodos desta biblioteca fornecem dados errados, entre em contato comigo e/ou envie alguns arquivos de amostra para [email protected].
Mas não posso (e não vou) consertar tudo. A coisa mais louca que eu já vi foi um ID3V2TAG com a seguinte codificação: UTF-16 (fina), terminado nulo (mais ou menos padrão), começando com um nascido (ok ...), personagem por caracteres (WTF ...?)-Sim, sem brincadeira. Um total de 6 bytes por personagem ...