Skip to content

Commit

Permalink
perf: Getter/Setter to avoid conflicts with other tags
Browse files Browse the repository at this point in the history
  • Loading branch information
eidoriantan committed Apr 29, 2020
1 parent 8d8d5f6 commit 0f1be08
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 54 deletions.
51 changes: 13 additions & 38 deletions src/id3v2/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,16 @@ import {
setBit, decodeSynch, encodeSynch, synch, mergeBytes
} from '../utils/bytes.mjs'

function filter (tags, version) {
tags.TIT2 = tags.TIT2 || tags.title || undefined
tags.TPE1 = tags.TPE1 || tags.artist || undefined
tags.TALB = tags.TALB || tags.album || undefined

if (version === 3) {
tags.TYER = tags.TYER || tags.year || undefined
} else if (version === 4) {
tags.TDRC = tags.TDRC || tags.year || undefined
}

tags.COMM = tags.COMM || (tags.comment !== '' ? [{
language: 'eng',
descriptor: '',
text: tags.comment
}] : undefined)

tags.TRCK = tags.TRCK || tags.track || undefined
tags.TCON = tags.TCON || tags.genre || undefined

const ids = Object.keys(frames)
const tagIds = Object.keys(tags).filter(key => ids.includes(key))
function filter (tags) {
const filtered = {}
const id = /^([A-Z0-9]{4})$/

if (tagIds.length === 0) return new ArrayBuffer(0)
tagIds.forEach(id => {
if (tags[id] !== undefined) filtered[id] = tags[id]
Object.entries(tags).forEach(element => {
const name = element[0]
const value = element[1]
if (name.match(id) && value !== undefined && value !== '') {
filtered[name] = value
}
})

return filtered
Expand Down Expand Up @@ -104,14 +87,6 @@ export function decode (buffer, tagOffset = 0) {
} else pushTag({ id: frame.id, value: frame.value })
}

tags.title = tags.TIT2
tags.artist = tags.TPE1
tags.album = tags.TALB
tags.year = version === 3 ? tags.TYER : (tags.TDRC && tags.TDRC.substr(0, 4))
tags.comment = tags.COMM && tags.COMM[0].text
tags.track = tags.TRCK && tags.TRCK.split('/')[0]
tags.genre = tags.TCON

return tags
}

Expand Down Expand Up @@ -164,8 +139,8 @@ export function validate (tags, strict, options) {
const { version } = options
if (version !== 3 && version !== 4) throw new TagError(200, 'Unknown version')

const filtered = filter(tags, version)
for (const id in filtered) {
tags = filter(tags)
for (const id in tags) {
if (!Object.keys(frames).includes(id)) continue

const frameSpec = frames[id]
Expand All @@ -185,16 +160,16 @@ export function validate (tags, strict, options) {
export function encode (tags, options) {
const { version, padding, unsynch } = options

const filtered = filter(tags, version)
const headerBytes = [0x49, 0x44, 0x33, version, 0]
let flagsByte = 0
const sizeView = new BufferView(4)
const paddingBytes = new Uint8Array(padding)
const framesBytes = []

for (const id in filtered) {
tags = filter(tags)
for (const id in tags) {
const frameSpec = frames[id]
const bytes = frameSpec.write(filtered[id], { id, version, unsynch })
const bytes = frameSpec.write(tags[id], { id, version, unsynch })
bytes.forEach(byte => framesBytes.push(byte))
}

Expand Down
92 changes: 76 additions & 16 deletions src/mp3tag.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,31 @@ import { mergeBytes } from './utils/bytes.mjs'
import { overwriteDefault, mergeObjects } from './utils/objects.mjs'
import { isBuffer } from './utils/types.mjs'

function mergeTags (tags) {
tags.TIT2 = tags.TIT2 || tags.title
tags.TPE1 = tags.TPE1 || tags.artist
tags.TALB = tags.TALB || tags.album
tags.TYER = tags.TYER || (tags.TDRC && tags.TDRC.substr(0, 4)) ||
tags.year
tags.COMM = tags.COMM || (tags.comment && [{
language: 'eng',
descriptor: '',
text: tags.comment
}])
tags.TRCK = tags.TRCK || tags.track
tags.TCON = tags.TCON || tags.genre

tags.title = tags.TIT2 || ''
tags.artist = tags.TPE1 || ''
tags.album = tags.TALB || ''
tags.year = tags.TYER || ''
tags.comment = (tags.COMM && tags.COMM[0].text) || ''
tags.track = (tags.TRCK && tags.TRCK.split('/')[0]) || ''
tags.genre = tags.TCON || ''

return tags
}

export default class MP3Tag {
constructor (buffer, verbose = false) {
if (!isBuffer(buffer)) {
Expand All @@ -30,21 +55,12 @@ export default class MP3Tag {
this.error = ''
this.errorCode = -1

let tags = {}
options = overwriteDefault(options, {
id3v1: true,
id3v2: true
})

let tags = {
title: '',
artist: '',
album: '',
year: '',
comment: '',
track: '',
genre: ''
}

try {
if (options.id3v1 && ID3v1.hasID3v1(this.buffer)) {
this.log('ID3v1 found, reading...')
Expand All @@ -66,7 +82,49 @@ export default class MP3Tag {
} else throw error
}

if (this.errorCode < 0) this.tags = tags
if (this.errorCode < 0) {
tags = mergeTags(tags)
Object.defineProperties(tags, {
title: {
get: function () { return this.TIT2 || '' },
set: function (value) { this.TIT2 = value }
},
artist: {
get: function () { return this.TPE1 || '' },
set: function (value) { this.TPE1 = value }
},
album: {
get: function () { return this.TALB || '' },
set: function (value) { this.TALB = value }
},
year: {
get: function () {
return this.TYER || (this.TDRC && this.TDRC.substr(0, 4)) || ''
},
set: function (value) { this.TYER = value }
},
comment: {
get: function () { return (this.COMM && this.COMM[0].text) || '' },
set: function (value) {
const comment = { language: 'eng', descriptor: '', text: value }
if (Array.isArray(this.COMM)) this.COMM[0] = comment
else this.COMM = [comment]
}
},
track: {
get: function () {
return (this.TRCK && this.TRCK.split('/')[0]) || ''
},
set: function (value) { this.TRCK = value }
},
genre: {
get: function () { return this.TCON || '' },
set: function (value) { this.TCON = value }
}
})

this.tags = tags
}
return this.tags
}

Expand All @@ -75,6 +133,7 @@ export default class MP3Tag {
this.errorCode = -1

const defaultVersion = this.tags.v2Version ? this.tags.v2Version[0] : 4
let tags = mergeTags(this.tags)
options = overwriteDefault(options, {
strict: false,
id3v1: { include: true },
Expand All @@ -90,22 +149,23 @@ export default class MP3Tag {
try {
if (options.id3v1.include) {
this.log('Validating ID3v1...')
ID3v1.validate(this.tags, options.strict)
ID3v1.validate(tags, options.strict)

this.log('Writing ID3v1...')
const tagBytes = new Uint8Array(ID3v1.encode(this.tags))
const encoded = ID3v1.encode(tags)
const tagBytes = new Uint8Array(encoded)
audio = mergeBytes(audio, tagBytes)
}

if (options.id3v2.include) {
this.log('Transforming ID3v2...')
this.tags = ID3v2.transform(this.tags, options.id3v2.version)
tags = ID3v2.transform(tags, options.id3v2.version)

this.log('Validating ID3v2...')
ID3v2.validate(this.tags, options.strict, options.id3v2)
ID3v2.validate(tags, options.strict, options.id3v2)

this.log('Writing ID3v2...')
const encoded = ID3v2.encode(this.tags, options.id3v2)
const encoded = ID3v2.encode(tags, options.id3v2)
const tagBytes = new Uint8Array(encoded)
audio = mergeBytes(tagBytes, audio)
}
Expand Down

0 comments on commit 0f1be08

Please sign in to comment.