AdpcmEncoder/encode_creative_adpcm_c.cpp
/**
 * Encodes the given sequence of unsigned 8bit values to 4bit ADPCM.
 * The first 8bit value is stored "as is", but the following values are
 * compressed to 4bit values. This almost halves the size.
 * 
 * The encoder uses an ADPCM decoder and tries every possible input
 * until it get the output that most closely matches the input value.
 * As there are only 16 possible input values to try with 4 bits
 * this is not impossibly slow.
 * 
 * This encoder seems to produce good results that sound similar to
 * the results that VOCEDIT 2 produces. It might of course be possible
 * to produce a better encoder, but as this encoder is good enough for
 * my purposes I have not tried.
 */
Encodes the given sequence of unsigned 8bit values to 4bit ADPCM.
The first 8bit value is stored "as is", but the following values are
compressed to 4bit values. This almost halves the size.

The encoder uses an ADPCM decoder and tries every possible input
until it get the output that most closely matches the input value.
As there are only 16 possible input values to try with 4 bits
this is not impossibly slow.

This encoder seems to produce good results that sound similar to
the results that VOCEDIT 2 produces. It might of course be possible
to produce a better encoder, but as this encoder is good enough for
my purposes I have not tried.
Encodes the given sequence of unsigned 8bit values to 4bit ADPCM . The first 8bit value is stored " as is " but the following values are compressed to 4bit values . This almost halves the size . The encoder uses an ADPCM decoder and tries every possible input until it get the output that most closely matches the input value . As there are only 16 possible input values to try with 4 bits this is not impossibly slow . This encoder seems to produce good results that sound similar to the results that VOCEDIT 2 produces . It might of course be possible to produce a better encoder but as this encoder is good enough for my purposes I have not tried .
std::vector<uint8_t> createAdpcm4BitFromRaw(const std::vector<uint8_t>& raw)
{
    CreativeAdpcmDecoder4Bit decoder(raw[0]);
    std::vector<uint8_t> result(raw.size() - 1);
    for (int i = 1; i < raw.size(); ++i)
    {
        int bestIndex = 0;
        int bestDiff = std::numeric_limits<int>::max();
        CreativeAdpcmDecoder4Bit bestDecoder(0);
        for (uint8_t n = 0; n < 16; ++n)
        {
            CreativeAdpcmDecoder4Bit decoderCopy = decoder;
            int diff = std::abs(decoderCopy.decodeNibble(n) - raw[i]);
            if (diff < bestDiff)
            {
                bestDiff = diff;
                bestIndex = n;
                bestDecoder = decoderCopy;
            }
        }
        decoder = bestDecoder;
        result[i-1] = bestIndex;
    }
    std::vector<uint8_t> binaryResult(result.size() / 2);
    for (int n = 0; n < result.size() / 2; ++n)
    {
        binaryResult[n] = ((result[2 * n] << 4) + (result[2 * n + 1]));
    }
    binaryResult.insert(binaryResult.begin(), raw[0]);
    return binaryResult;
}
std :: vector < uint8_t > createAdpcm4BitFromRaw ( const std :: vector < uint8_t > & raw ) { CreativeAdpcmDecoder4Bit decoder ( raw [ 0 ] ) ; std :: vector < uint8_t > result ( raw . size ( ) - 1 ) ; for ( int i = 1 ; i < raw . size ( ) ; ++ i ) { int bestIndex = 0 ; int bestDiff = std :: numeric_limits < int > :: max ( ) ; CreativeAdpcmDecoder4Bit bestDecoder ( 0 ) ; for ( uint8_t n = 0 ; n < 16 ; ++ n ) { CreativeAdpcmDecoder4Bit decoderCopy = decoder ; int diff = std :: abs ( decoderCopy . decodeNibble ( n ) - raw [ i ] ) ; if ( diff < bestDiff ) { bestDiff = diff ; bestIndex = n ; bestDecoder = decoderCopy ; } } decoder = bestDecoder ; result [ i - 1 ] = bestIndex ; } std :: vector < uint8_t > binaryResult ( result . size ( ) / 2 ) ; for ( int n = 0 ; n < result . size ( ) / 2 ; ++ n ) { binaryResult [ n ] = ( ( result [ 2 * n ] << 4 ) + ( result [ 2 * n + 1 ] ) ) ; } binaryResult . insert ( binaryResult . begin ( ) , raw [ 0 ] ) ; return binaryResult ; }
Encodes the given sequence of unsigned 8bit values to 4bit ADPCM.
Encodes the given sequence of unsigned 8bit values to 4bit ADPCM .
// try every possible input for the decoder // merge nibbles into bytes