Skip to content

Commit

Permalink
Merge pull request Borewit#1291 from Borewit/aiff-text-chunks
Browse files Browse the repository at this point in the history
Add AIFF text chunk support, resulting in AIFF metadata & mapping
  • Loading branch information
Borewit authored Sep 18, 2022
2 parents d0aecc0 + d17547d commit e08ee03
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 118 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Following tag header formats are supported:
* [iTunes](https://github.com/sergiomb2/libmp4v2/wiki/iTunesMetadata)
* [RIFF](https://wikipedia.org/wiki/Resource_Interchange_File_Format)/INFO
* [Vorbis comment](https://wikipedia.org/wiki/Vorbis_comment)
* [AIFF](https://wikipedia.org/wiki/Audio_Interchange_File_Format)

It allows many tags to be accessed in audio format, and tag format independent way.

Expand Down
224 changes: 112 additions & 112 deletions doc/common_metadata.md

Large diffs are not rendered by default.

16 changes: 15 additions & 1 deletion lib/aiff/AiffParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ export class AIFFParser extends BasicParser {
debug('Reading AIFF chunk at offset=' + this.tokenizer.position);
const chunkHeader = await this.tokenizer.readToken<iff.IChunkHeader>(iff.Header);

debug(`Chunk id=${chunkHeader.chunkID}`);
const nextChunk = 2 * Math.round(chunkHeader.chunkSize / 2);
const bytesRead = await this.readData(chunkHeader);
await this.tokenizer.ignore(nextChunk - bytesRead);
Expand Down Expand Up @@ -102,9 +101,24 @@ export class AIFFParser extends BasicParser {
}
return 0;

case 'NAME': // Sample name chunk
case 'AUTH': // Author chunk
case '(c) ': // Copyright chunk
case 'ANNO': // Annotation chunk
return this.readTextChunk(header);

default:
debug(`Ignore chunk id=${header.chunkID}, size=${header.chunkSize}`);
return 0;
}
}

public async readTextChunk(header: iff.IChunkHeader): Promise<number> {
const value = await this.tokenizer.readToken(new Token.StringType(header.chunkSize, 'ascii'));
value.split('\0').map(v => v.trim()).filter(v => v && v.length > 0).forEach(v => {
this.metadata.addTag('AIFF', header.chunkID, v.trim());
});
return header.chunkSize;
}

}
20 changes: 20 additions & 0 deletions lib/aiff/AiffTagMap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { INativeTagMap } from '../common/GenericTagTypes.js';
import { CommonTagMapper } from '../common/GenericTagMapper.js';

/**
* ID3v1 tag mappings
*/
const tagMap: INativeTagMap = {
NAME: 'title',
AUTH: 'artist',
'(c) ': 'copyright',
ANNO: 'comment'
};

export class AiffTagMapper extends CommonTagMapper {

public constructor() {
super(['AIFF'], tagMap);
}
}

4 changes: 3 additions & 1 deletion lib/common/CombinedTagMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { RiffInfoTagMapper } from '../riff/RiffInfoTagMap.js';
import { ITag } from '../type.js';
import { INativeMetadataCollector } from './MetadataCollector.js';
import { MatroskaTagMapper } from '../matroska/MatroskaTagMapper.js';
import { AiffTagMapper } from '../aiff/AiffTagMap.js';

export class CombinedTagMapper {

Expand All @@ -27,7 +28,8 @@ export class CombinedTagMapper {
new APEv2TagMapper(),
new AsfTagMapper(),
new RiffInfoTagMapper(),
new MatroskaTagMapper()
new MatroskaTagMapper(),
new AiffTagMapper()
].forEach(mapper => {
this.registerTagMapper(mapper);
});
Expand Down
2 changes: 1 addition & 1 deletion lib/common/GenericTagTypes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export type TagType = 'vorbis' | 'ID3v1' | 'ID3v2.2' | 'ID3v2.3' | 'ID3v2.4' | 'APEv2' | 'asf' | 'iTunes' | 'exif' | 'matroska';
export type TagType = 'vorbis' | 'ID3v1' | 'ID3v2.2' | 'ID3v2.3' | 'ID3v2.4' | 'APEv2' | 'asf' | 'iTunes' | 'exif' | 'matroska' | 'AIFF';

export interface IGenericTag {
id: GenericTagId,
Expand Down
4 changes: 2 additions & 2 deletions lib/common/MetadataCollector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { fileTypeFromBuffer } from 'file-type';

const debug = initDebug('music-metadata:collector');

const TagPriority: TagType[] = ['matroska', 'APEv2', 'vorbis', 'ID3v2.4', 'ID3v2.3', 'ID3v2.2', 'exif', 'asf', 'iTunes', 'ID3v1'];
const TagPriority: TagType[] = ['matroska', 'APEv2', 'vorbis', 'ID3v2.4', 'ID3v2.3', 'ID3v2.2', 'exif', 'asf', 'iTunes', 'AIFF', 'ID3v1'];

/**
* Combines all generic-tag-mappers for each tag type
Expand Down Expand Up @@ -97,7 +97,7 @@ export class MetadataCollector implements INativeMetadataCollector {
this.originPriority[tagType] = priority++;
}
this.originPriority.artificial = 500; // Filled using alternative tags
this.originPriority.id3v1 = 600; // Consider worst due to field length limit
this.originPriority.id3v1 = 600; // Consider as the worst because of the field length limit
}

/**
Expand Down
14 changes: 13 additions & 1 deletion test/test-file-aiff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,21 @@ describe('Parse AIFF (Audio Interchange File Format)', () => {
assert.strictEqual(format.codec, 'PCM', 'format.codec');

assert.strictEqual(common.album, 'Hdtracks 2020 Hi-Res Sampler', 'common.album');
assert.deepEqual(common.artists, ['Chris Jones'], 'common.artists');
assert.deepStrictEqual(common.artists, ['Chris Jones'], 'common.artists');
assert.strictEqual(common.encodersettings, 'Lavf58.29.100', 'common.encodersettings');
assert.strictEqual(common.year, 2020, 'common.year');
});

it('text chunks', async () => {

const filePath = path.join(aiffSamplePath, 'M1F1-AlawC-AFsp.aif');

const {format, common} = await mm.parseFile(filePath);

assert.strictEqual(format.container, 'AIFF-C', 'format.container');
assert.strictEqual(format.codec, 'Alaw 2:1', 'format.codec');

assert.deepStrictEqual(common.comment, ['AFspdate: 2003-01-30 03:28:34 UTC', 'user: kabal@CAPELLA' ,'program: CopyAudio'], 'common.comment');
});

});

0 comments on commit e08ee03

Please sign in to comment.