A module for working with Interchange File Format (IFF) data.
$ npm install interchange-file-format
The 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 chunk
Create 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 ID
s.
const form = Group.from(bufferSource) // `bufferSource` could be a AIFF file on disk
A 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