Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
M
mqa
Manage
Activity
Members
Labels
Plan
Issues
6
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Mans Rullgard
mqa
Commits
9e27ee11
Commit
9e27ee11
authored
6 years ago
by
Mans Rullgard
Browse files
Options
Downloads
Patches
Plain Diff
document bitstream format
parent
7bdb3451
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
mqa.rst
+458
-0
458 additions, 0 deletions
mqa.rst
with
458 additions
and
0 deletions
mqa.rst
0 → 100644
+
458
−
0
View file @
9e27ee11
====================
MQA bitstream format
====================
The primary MQA bitstream is formed by the XOR of one bit from each
left/right sample pair. The position of this bit within the 24-bit
samples is in the range 8-15 inclusive.
This document describes the format of the MQA bitstream. All fields are
read least significant bit first. Where possible, names are aligned
with text strings found within the decoder binary.
Packet structure
~~~~~~~~~~~~~~~~
The MQA bitstream is structured as a sequence of packets. Each packet
begins with a 4-bit type identifier and ends with a 4-bit checksum.
The size and interpretation of the intervening payload depends on the
packet type. ::
mqa_stream() {
for (;;) {
mqa_packet()
}
}
mqa_packet() {
packet_type uint(4)
if (packet_type == 0) {
hole()
} else if (packet_type == 1) {
reconstruction()
} else if (packet_type == 2) {
data()
} else if (packet_type == 3) {
terminate()
} else if (packet_type == 4) {
authentication()
} else if (packet_type == 5) {
datasync()
} else if (packet_type == 5) {
packet_6()
} else if (packet_type == 7) {
metadata()
} else if (packet_type == 8) {
key()
}
checksum uint(4)
}
`packet_type`
===== ==============
Value Type
===== ==============
0 hole
1 reconstruction
2 data
3 terminate
4 authentication
5 datasync
6 packet_6
7 metadata
8 key
===== ==============
`checksum`
CRC computed over the `packet_type` field and the payload.
Packet types
~~~~~~~~~~~~
Hole
----
Hole packets serve as padding in the bitstream. The payload is ignored
apart from the checksum calculation. ::
hole() {
size uint(4)
if (size == 15) {
size uint(12)
}
junk bits(size)
}
`size`
Number of following bits to skip.
`junk`
Ignored.
Reconstruction
--------------
Reconstruction packets carry touchup data for the audio base band. ::
reconstruction() {
size uint(12)
data bits(size)
}
`size`
Number of following data bits.
`data`
Touchup data.
Data
----
The purpose of this packet type is unknown. ::
data() {
unknown uint(8)
size uint(12)
data bits(size)
}
`size`
Number of following data bits.
`data`
Data bits.
Terminate
---------
Terminate packets indicate the end position of an MQA stream. ::
terminate() {
bits_to_end uint(17)
}
`bits_to_end`
Number of bits in stream following this packet.
Authentication
--------------
These packets carry encrypted data for authentication of the audio
stream. ::
authentication() {
auth_level uint(4)
auth_data bits(3072)
}
`auth_level`
Authentication level provided. Matches the field with the same name
in the `datasync` packet. Also specifies decryption key.
`auth_data`
Encrypted authentication data.
Authentication data
"""""""""""""""""""
The authentication data is decrypted using the RSA algorithm with a
separate key for each `auth_level` value. It is then further
descrambled using the BLAKE2s hash function. The format of the thus
decrypted data is detailed below. ::
auth_data() {
unknown bits(63)
auth_lsb uint(1)
unknown bits(24)
auth_info bits(4)
auth_level uint(4)
stage2_crc uint(32)
stage1_hash bits(256)
lsb_hash[0] bits(256)
lsb_hash[1] bits(256)
lsb_hash[2] bits(256)
lsb_hash[3] bits(256)
lsb_hash[4] bits(256)
lsb_hash[5] bits(256)
lsb_hash[6] bits(256)
lsb_hash[7] bits(256)
lsb_hash[8] bits(256)
unknown bits(32)
pad bits(96)
auth_hash bits(256)
}
`auth_lsb`
1 if low 8 bits are authenticated.
`auth_info`
Matches field with same name in `datasync` packet.
`auth_level`
Matches field with same name in `datasync` packet.
`stage2_crc`
CRC-32 of audio data after stage 2 decoding.
`stage1_hash`
BLAKE2s hash of top 16 bits of audio data after stage 1 decoding.
`lsb_hash`
BLAKE2s hash of the low 8 bits of the input stream. Any of the 9
provided hashes may match.
`auth_hash`
BLAKE2s hash of the preceding `auth_data` bits.
Datasync
--------
This packet type identifies the stream as MQA and provides basic
information for the decoder. ::
datasync() {
magic uint(36)
stream_pos_flag uint(1)
unused bits(1)
orig_rate uint(5)
src_rate uint(5)
render_filter uint(5)
unknown uint(5)
unknown uint(1)
unknown uint(1)
unused bits(1)
auth_info uint(4)
auth_level uint(4)
item_count uint(7)
for (i = 0; i < item_count; i++) {
size[i] uint(8)
}
for (i = 0; i < item_count; i++) {
type[i] uint(8)
}
if (stream_pos_flag) {
stream_position uint(32)
}
for (i = 0; i < item_count; i++) {
if (type[i] == 0) {
ds_item_0()
} else if (type[i] == 1) {
ds_item_1()
} else if (type[i] == 2) {
ds_item_2()
} else if (type[i] == 3) {
cipher_data()
}
}
}
`magic`
The 36-bit value 0x11319207d.
`stream_pos_flag`
0 if this is the first packet, 1 otherwise.
`orig_rate`
Original sample rate of audio.
`src_rate`
Sample rate of this stream.
`render_filter`
Index of upsampling filter to use in the render stage.
`auth_info`
Unknown meaning. Also present in encrypted `auth_data`.
`auth_level`
Authentication level provided for this stream. Values greater than or
equal to 9 indicate "Studio" or "blue" level. Lower values indicate
"green" level.
`item_count`
Number of additional data items contained in this packet.
`size[i]`
Size in bits of each additional data item.
`type[i]`
Type of each additional data item.
`stream_position`
Indicates the sample position of the first bit of this packet within
the MQA stream. If absent, a value of 0 is implied.
The `orig_rate` and `src_rate` fields are composed of a 2-bit base rate
index (MSBs) and a 3-bit scale factor (LSBs).
===== ==========
Index Rate (kHz)
===== ==========
0 44.1
1 48
2 64
3 invalid
===== ==========
===== ==========
Scale Multiplier
===== ==========
0 1
1 2
2 4
3 8
4 16
5 32
6 64
7 128
===== ==========
The fixed fields are followed by additional data items according to the
`type` and `size` arrays.
Type 0
""""""
Parameters releated to reconstruction of base band audio. ::
ds_item_0() {
stage2_dither uint(2)
gain_index uint(4)
unknown uint(7)
unknown uint(7)
if (stream_pos_flag) {
start_pos uint(27)
pad bits(1)
data bits(*)
}
}
`stage2_dither`
Indicates whether stage 2 reconstruction uses pseudo-random dither.
`gain_index`
Table index for amount of stage 2 gain.
`start_pos`
Sample position divided by 32 at which data applies.
`data`
Priming values for dither shaping filter.
Type 1
""""""
Parameters related to decoding of data carried in low 8 bits. ::
ds_item_1() {
unknown uint(6)
unknown uint(2)
unknown uint(1)
unknown uint(2)
if (stream_pos_flag) {
unknown uint(8)
unknown uint(1)
offset sint(12)
}
}
Type 2
""""""
Type 2 data items contain a subset of the type 1 fields. ::
ds_item_2() {
unknown uint(6)
unknown uint(2)
if (stream_pos_flag) {
unknown uint(3)
unknown uint(1)
offset sint(12)
}
}
Cipher data
"""""""""""
If this item is present, bits 16-21 of the audio data are descrambled
using the Salsa20 stream cipher. ::
cipher_data() {
cipher_iv uint(64)
start_pos uint(32)
}
`cipher_iv`
64-bit IV for use with the Salsa20 stream cipher.
`start_pos`
Sample position at which `cipher_iv` becomes valid.
Packet 6
--------
Unknown data, ignored by the decoder. ::
packet_6() {
size uint(12)
data bits(size)
}
Metadata
--------
Metadata packets carry information such as track title and artist name
in ID3v2 or some other format. Metadata blocks larger than 256 octets
may be fragmented across multiple MQA packets. ::
metadata() {
metadata_type uint(7)
is_last uint(1)
fragment_number uint(12)
size uint(8)
for (i = 0; i < size + 1; i++) {
data uint(8)
}
}
`metadata_type`
===== =======
Value Format
===== =======
1 ID3v2
2 unknown
===== =======
`is_last`
1 of this is the last fragment, 0 otherwise
`fragment_number`
The fragment number contained in this packet.
`size`
Payload size in octets minus 1.
Key
---
Cryptographic key data, purpose unclear. ::
key() {
size uint(12)
unknown uint(32)
data bits(*)
}
`size`
Number of following bits in packet.
`data`
Key data, 2048 bits expected.
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment