A module for working with Interchange File Format (IFF) data.
$ npm install interchange-file-formatThe following example implements a few structures for the AIFF (Audio Interchange File Format)
const { Form, Chunk, extensions } = require('interchange-file-format')
const fs = require('fs')
extensions.set('COMM', class CommonChunk extends Chunk {
get numChannels() { return this.readUIntBE(0, 2) }
get numSampleFrames() { return this.readUIntBE(2, 4) }
get sampleSize() { return this.readUIntBE(6, 2) }
get sampleRate() {
const x = this.readUIntBE(8, 2)
const y = this.readUIntBE(10, 1)
const z = this.readUIntBE(11, 1)
const pre = 16398
const pad = x - pre
const shifted = (y << 8) + z
return shifted << pad
}
})
extensions.set('SSND', class SoundDataChunk extends Chunk {
get offset() { return this.readUIntBE(0, 4) }
get blockSize() { return this.readUIntBE(4, 4) }
get soundData() { return this.slice(8) }
})
const stream = fs.createReadStream('/path/to/audio/track.aif')
const form = new Form({ type: 'AIFF' })
stream.pipe(form.createWriteStream()).on('finish', () => {
for (const chunk of form) {
// `chunk` could be `CommonChunk` or `SoundDataChunk` when `COMM`
// and `SSND` chunk IDs are foud
console.log(chunk)
}
})The ID class represents a container for 32 bits of characters, the
concatenation of four printable ASCII character in the range ' ' (SP, 0x20)
through '~' (0x7E). Spaces (0x20) cannot precede printing characters;
trailing spaces are allowed. Control characters are forbidden.
The ID class extends Uint8Array and is polymorphic with the Buffer
API.
Creates a 4 byte ID instance from a Buffer or string. A Chunk
can be identified by an ID. A Form will use an ID to describe its
type.
const id = ID.from('FORM')Set id value bytes on ID instance.
if (!id.set(bytesOrString)) {
// bytes invalid or too large
}Convert ID instance directly to Buffer, using the same internal
ArrayBuffer for this instance.
const buffer = id.toBuffer()The Chunk class is a container for bytes with a known ID and size.
A Chunk can be manually constructed or derived from an existing buffer
(see Chunk.from()).
Create a new Chunk instance from ID with options where options can
be:
{
size: required, // size in bytes of chunk body
ancestor: null // the ancestor this chunk is derived from
}const chunk = new Chunk('FORM', { size: 32 }) // 32 byte chunk body
chunk.set(bytes) // set bytes on chunkCreate a new Chunk from a given buffer with constructor options.
const chunk = Chunk.from(bufferFromSource)A Buffer pointer to the Chunk data.
Set bytes or a string on Chunk.
Map over the chunks in this chunk returning a new Chunk instance.
Filter over the chunks in this chunk returning a new Chunk instance.
Creates a new Chunk instance as a slice from this instance.
Convert Chunk into an Array.
Converts (serializes) the Chunk to a Buffer, including the ID and size
bytes as header values.
A Chunk iterator that implements the Iterator Protocol and
satisfies the Iterable interface requirements.
Creates a new ChunkIterator from a given buffer starting at an
optional offset.
const iterator = ChunkIterator.from(bufferSource)
for (const chunk of iterator) {
console.log('%s', chunk.id, chunk)
}An abstract class that extends Array that behaves like a container that
for many things. Classes like Form and List extend this type for the
FORM and LIST chunk types, respectively.
Creates a new Group from a given ID with options where option
can be:
{
type: required, // A string type name for the group, this could be the
// FORM type, or the record type for a LIST
}const group = new Group('FORM', { type: 'TEST' })Creates a new Group instance from a given buffer, loading types
and extensions based on parsed chunk IDs.
const form = Group.from(bufferSource) // `bufferSource` could be a AIFF file on diskA concatenated buffer of all chunks in this group.
Append a chunk or an array of chunks to the group, setting this instance as the chunks ancestor.
Pushes a new Chunk into the group, setting this instance
as the chunks ancestor.
"Unshifts" or left pushes a new Chunk into the group, setting this
instance as the chunks ancestor.
Shift a chunk out of the group, removing a reference to this instance as the ancestor.
Pop a chunk out of the group, removing a reference to this instance as the ancestor.
Concatenates and returns a new Group instance with given chunks (or
Group).
Map over the chunks in this group returning a new Group instance.
Filter over the chunks in this group returning a new Group instance.
Creates a new Group instance as a slice from this instance.
Convert this instance into an Array.
Creates a buffer from this Group instance flattening all
chunks in the hierarchy.
Get a ReadStream for chunks in a Group instance.
Get a WriteStream for writing chunks in a Group instance.
A Group type with an ID set to FORM.
A Group type with an ID set to LIST.
A special Group type with an ID set to LIST with a restriction on
the types of descendants being only other Group types.
A static Map of Group extensions that map a 4 byte chunk ID string
to a class that extends Group or Chunk to handle extensions to the
EA IFF 85 spec, such as AIFF (or AIFC) with the NAME or SSND types.
const { Chunk, Group, extensions } = require('interchange-file-format')
class TextChunk extends Chunk {
get text() {
return this.slice(0, this.size).toString()
}
}
// when then `NAME` or `AUTH` chunk ID is seen in a `Group`, this class will be used
extensions.set('NAME', TextChunk)
extensions.set('AUTH', TextChunk)MIT