I like your magic_id better :)
The reason I looked at the mode byte is because that's what c2enc/c2dec
(by way of a #define) use to set up the codec2 instance.
codec2.h:
#define CODEC2_MODE_1300 4
c2enc.c:
mode = CODEC2_MODE_1300;
...
codec2 = codec2_create(mode);
Samples per frame, bits per frame, etc are all defined in the codec2
internal structure:
nsam = codec2_samples_per_frame(codec2);
nbit = codec2_bits_per_frame(codec2);
So it really doesn't make sense to represent these values in the header
when the code can figure it out from a single byte.
samplerate is something of a sticky wicket. For now the only outlier is
WB at 16Khz. Ideally I'd like to see the whole pipeline work at 48KHz
and let the FFT do the voodoo, but that's a whole other thread. I think
I'll leave that alone for now.
It might make sense to keep a flags byte around for --natural and
--softdec. I haven't used these so I don't know much about them.
At present we don't do any FEC in the raw streams, only on the air (eg:
with freedv_tx/rx not c2enc/dec).
The version stuff might be useful for detecting future backward
incompatible changes, but my gut feeling is YAGNI. I'd be interested to
hear David's thoughts on that.
So, that leaves us with a simpler header:
struct Codec2Header{
magic_identification :u24b, // offset 0 bytes
// const 0xC0DEC2 ([0xC0,0xDE,0xC2])
major_version :u8, // offset 3 bytes //
minor_version :u8, // offset 4 bytes //
mode_id :u8, // offset 5 bytes //
flags :u8, // offset 6 bytes // default 0
};
Two bytes less if we ignore the version stuff.
My plan is to add some code to c2enc/dec to see if the codec2 filename
argument ends in ".c2".
In the case of the encoder, if it sees that file extension, it will
write the file header and then proceed to write as normal. Otherwise
behave as it does today.
In the decoder, if that extension, try to parse the header and set the
mode. If the magic is wrong, seek the file back to zero and honor the
command line mode argument / flags. I don't want to change the argument
order as to not break old scripts. This means when using a valid .c2
file the mode argument could be invalid, eg: ./c2dec foobar test.c2 -
73 de Kevin N8VNR
Hi folks!
Post by Kevin OtteThat said, the notion of managing the different bitrates does present a
challenge. I therefore suggest any such encoded file have some "magic"
bytes at the beginning, even if this is something as simple as 0x43 0x32
("C2"). I then propose the next byte be the mode ID as defined in
codec2.h. This would allow c2enc/c2dec to be retrofitted or separate
tools to be constructed to Do The Right Thing™ based on these.
May I suggest a bitstream header format that encodes all the profile
parameters, so that new profiles can be added without changing the
header format or adding new "magic" numbers for profiles.
73 de txp0wer
Post by Kevin OtteIf we can agree on these bytes, I'm happy to take a stab at coding this
up. It doesn't look like it should be too difficult (famous last words!)
73 de Kevin N8VNR
Post by Kevin Ottehttps://matroska.org/technical/specs/index.html
Post by Bruce PerensSee https://www.xiph.org/ogg/doc/rfc3533.txt . Make it work with the
Ogg Encapsulation Format.
<code language="pseudocode" style="Rust">
// u8 == unsigned 8-bit integer
// u16b == unsigned 16-bit integer, big endian
struct Codec2Header{
magic_identification :u24b, // offset 0 bytes
// const 0xC0DEC2 ([0xC0,0xDE,0xC2])
major_version :u8, // offset 3 bytes //
minor_version :u8, // offset 4 bytes //
forward_ec_level :u8, // offset 6 bytes //
flags :u8, // offset 5 bytes // default 0
subframes_per_frame :u8, // offset 7 bytes // 1 to 4
samples_per_subframe :u16b, // offset 8 bytes
samplerate_hz :u16b // offset 10 // default 8000
};
struct Codec2SubframeParameters{ // offset 12
// repeated [subframes_per_frame] times
lsp_bits_per_frame :u8, // offset 12+4*n
pitch_bits_per_frame :u8, // offset 12+4*n+(0..1)
energy_bits_per_frame :u8, // offset 4*n+(0..1)
voicing_bits_per_frame :u8 // offset 4*n+(0..1)
}
match forward_ec_level{
0=>none,
1=>"1200",
2=>"1850",
3=>"2000",
_=>undefined
}
0x01=NATURAL_BYTE_ORDER // --natural
0x02=ALTERNATE_MODE_1 // "B"
0x04=ALTERNATE_MODE_2 // "C", "D"
0x08=ALTERNATE_MODE_4 // "E" .. "H"
0x10=unused
0x20=unused
0x40=unused
0x80=ALTERNATE_CODEBOOK_1
</code>
example (hex)
# "3200" default profile
# begin Codec2Header
00: C0 DE C2
03: 00 04 # version 0.4
05: 00 # no forward error correction
06: 00 # flags: gray code, no alternate profile, no alternate codebook
07: 02 # 2 subframes per frame
08: 00 a0 # 160 samples per subframe => 320 samples per frame
0a: 1f 40 # 8000 Hz
# end Codec2Header, begin Codec2SubframeParameters
# # begin subframe 0 # if I understand codec2_encode_3200() right
0c: 20 # 32 bits LSP
0d: 00 # 0 bits pitch
0e: 00 # 0 bits energy
0f: 00 # 0 bits voicing
# # end subframe 0, begin subframe 1
10: 12 # 18 bits LSP
11: 07 # 0 bits pitch
12: 05 # 0 bits energy
13: 02 # 0 bits voicing
# # end subframe 1
# end Codec2SubframeParameters, begin data bitstream
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Freetel-codec2 mailing list
https://lists.sourceforge.net/lists/listinfo/freetel-codec2