A movie has two kinds of sound. An event sound is defined once with DefineSound and started by StartSound, a button or a script. A streaming sound belongs to a timeline: SoundStreamHead gives its format, and each frame carries its share in a SoundStreamBlock, so it plays in step with the frames. The explorer plays uncompressed and ADPCM sounds and counts the frames of MP3.
Sound formats
Every sound tag starts with a 4-bit format, a 2-bit rate, a size bit and a channel bit.
| SoundFormat | Coding | From SWF |
|---|---|---|
| 0 | Uncompressed, in the byte order of the machine that wrote it | 1 |
| 1 | ADPCM | 1 |
| 2 | MP3 | 4 |
| 3 | Uncompressed, little-endian | 4 |
| 4 | Nellymoser 16 kHz | 10 |
| 5 | Nellymoser 8 kHz | 10 |
| 6 | Nellymoser | 6 |
| 11 | Speex | 10 |
| Field | Values |
|---|---|
| SoundRate, UB[2] | 0 5.5 kHz, 1 11 kHz, 2 22 kHz, 3 44 kHz: 5,512, 11,025, 22,050 and 44,100 Hz |
| SoundSize, UB[1] | 0 8-bit, 1 16-bit; always 1 for compressed formats |
| SoundType, UB[1] | 0 mono, 1 stereo |
8-bit samples are unsigned and 16-bit samples signed. Format 0’s byte order is that of the machine that made the file, so 16-bit data in it is ambiguous; the specification says to use format 3 instead. The explorer reads format 0 as little-endian, which is an assumption.
DefineSound (14)
| Type | Name | Meaning |
|---|---|---|
| UI16 | SoundId | The character ID |
| UB[4] | SoundFormat | See sound formats |
| UB[2] | SoundRate | The sample rate |
| UB[1] | SoundSize | 8 or 16-bit |
| UB[1] | SoundType | Mono or stereo |
| UI32 | SoundSampleCount | Samples, per channel |
| bytes | SoundData | The sound, to the end of the tag; for MP3, SI16 SeekSamples then MP3 frames |
StartSound (15)
| Type | Name | Meaning |
|---|---|---|
| UI16 | SoundId | The sound to start or stop |
| SOUNDINFO | SoundInfo | How to play it |
StartSound2 (89, SWF 9)
| Type | Name | Meaning |
|---|---|---|
| STRING | SoundClassName | The ActionScript 3 class of the sound |
| SOUNDINFO | SoundInfo | How to play it |
SOUNDINFO
| Type | Name | Meaning |
|---|---|---|
| UB[2] | Reserved | 0 |
| UB[1] | SyncStop | Stop the sound |
| UB[1] | SyncNoMultiple | Do not start it if it is already playing |
| UB[1] | HasEnvelope | An envelope follows |
| UB[1] | HasLoops | A loop count follows |
| UB[1] | HasOutPoint | An out point follows |
| UB[1] | HasInPoint | An in point follows |
| UI32 | InPoint | If HasInPoint: where to start, in samples at 44 kHz |
| UI32 | OutPoint | If HasOutPoint: where to stop, in samples at 44 kHz |
| UI16 | LoopCount | If HasLoops: how many times to play it |
| UI8 | EnvPoints | If HasEnvelope: the number of envelope points |
| SOUNDENVELOPE × EnvPoints | EnvelopeRecords | Each UI32 Pos44 (samples at 44 kHz), UI16 LeftLevel, UI16 RightLevel (0 to 32,768) |
SoundStreamHead (18)
| Type | Name | Meaning |
|---|---|---|
| UB[4] | Reserved | 0 |
| UB[2] | PlaybackSoundRate | The rate to play at |
| UB[1] | PlaybackSoundSize | 8 or 16-bit |
| UB[1] | PlaybackSoundType | Mono or stereo |
| UB[4] | StreamSoundCompression | The format of the blocks: ADPCM, or from SWF 4 MP3 |
| UB[2] | StreamSoundRate | The rate of the data |
| UB[1] | StreamSoundSize | 8 or 16-bit |
| UB[1] | StreamSoundType | Mono or stereo |
| UI16 | StreamSoundSampleCount | The average number of samples a frame |
| SI16 | LatencySeek | MP3 only: samples to skip at the start |
One per timeline, before its first SoundStreamBlock.
SoundStreamHead2 (45, SWF 3)
The same fields as SoundStreamHead, but any format is allowed in StreamSoundCompression, including uncompressed and Nellymoser.
SoundStreamBlock (19)
One frame’s share of the stream, the whole body: for ADPCM, as far as is known, a complete ADPCM run with its own code size; for MP3, UI16 SampleCount, SI16 SeekSamples and then MP3 frames; for uncompressed sound, the samples.
MP3 in SWF
MP3 data is ordinary MPEG audio layer III frames, MPEG-1, 2 or 2.5. In a DefineSound it is MP3SOUNDDATA: SI16 SeekSamples, the samples to skip at the start, then the frames. In a SoundStreamBlock it is UI16 SampleCount, SI16 SeekSamples, then the frames. An MPEG-1 frame holds 1,152 samples, an MPEG-2 or 2.5 frame 576. The explorer walks the frame headers to count frames and give the length; it does not decode them.
SWF ADPCM
Flash’s own ADPCM, close to IMA ADPCM, with 2 to 5 bits a sample. The data is read as bits, most significant first, with no byte alignment between packets:
- UB[2]
AdpcmCodeSize: bits a code minus 2 (0 is 2 bits, 3 is 5). - Packets of 4,096 samples a channel, the last perhaps shorter. Each starts, for each
channel, left first, with SB[16]
InitialSampleand UB[6]InitialIndex; InitialSample is the packet’s first output sample. Then 4,095 codes a channel, interleaved left, right, left … for stereo.
Each code of bits bits is decoded with the channel’s predictor p and step index i:
- step = STEPS[i].
- diff = 0. For each magnitude bit, from the highest (value 2bits − 2) to the lowest: if it is set, diff += step; then step = step >> 1. After the loop, diff += step.
- If the sign bit (2bits − 1) is set, p −= diff, otherwise p += diff. Clamp p to −32,768 … 32,767.
- i += INDEX[bits][magnitude]; clamp i to 0 … 88.
- Output p.
| Bits | INDEX by magnitude (sign bit removed) |
|---|---|
| 2 | −1, 2 |
| 3 | −1, −1, 2, 4 |
| 4 | −1, −1, −1, −1, 2, 4, 6, 8 |
| 5 | −1, −1, −1, −1, −1, −1, −1, −1, 1, 2, 4, 6, 8, 10, 13, 16 |
STEPS is the standard IMA step table of 89 entries:
7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230,
253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
32767
This follows FFmpeg’s SWF ADPCM decoder, which follows the specification’s ADPCM section.