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 On 07/24/2017 01:05 PM, txp0wer via Freetel-codec2 wrote: > Hi folks! > >> That 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 > >> >> If 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 >> >> On 05/22/2017 04:35 PM, Kevin Otte wrote: >>> Or Matroska (.mka): >>> https://matroska.org/technical/specs/index.html >>> >>> On 05/22/2017 02:28 PM, Bruce Perens wrote: >>>> See https://www.xiph.org/ogg/doc/rfc3533.txt . Make it work with the >>>> Ogg Encapsulation Format. > > <code language="pseudocode" style="Rust"> > // data types: > // 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 > } > > flags: > 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 > Freetel-codec2@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/freetel-codec2 > ------------------------------------------------------------------------------ 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 Freetel-codec2@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/freetel-codec2