1
0
mirror of https://github.com/ScrelliCopter/VGM-Tools synced 2025-02-21 04:09:25 +11:00

dsptool: refactor

This commit is contained in:
2023-03-19 09:58:26 +11:00
parent ac89564669
commit 99bf061438
9 changed files with 848 additions and 804 deletions

View File

@@ -1,9 +1,18 @@
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
project(DspTool LANGUAGES C)
set(CMAKE_C_STANDARD 99)
option(BUILD_SHARED_LIBS "Build as a Shared Object or DLL" ON)
set(HEADERS dsptool.h)
set(HEADERS common.h dsptool.h)
set(SOURCES math.c decode.c encode.c)
add_library(DspTool ${HEADERS} ${SOURCES})
set_property(TARGET DspTool PROPERTY C_STANDARD 99)
if (BUILD_SHARED_LIBS)
target_compile_definitions(DspTool PRIVATE BUILD_SHARED)
else()
target_compile_definitions(DspTool PRIVATE BUILD_STATIC)
endif()
target_compile_options(DspTool PRIVATE
$<$<C_COMPILER_ID:AppleClang,Clang,GNU>:-Wall -Wextra -pedantic -Wno-unused-parameter>
$<$<C_COMPILER_ID:MSVC>:/Wall /wd4100>)

View File

@@ -1,101 +0,0 @@
#include <stdint.h>
#include "dsptool.h"
#include <limits.h>
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
inline int DivideByRoundUp(int dividend, int divisor)
{
return (dividend + divisor - 1) / divisor;
}
inline char GetHighNibble(char value)
{
return value >> 4 & 0xF;
}
inline char GetLowNibble(char value)
{
return value & 0xF;
}
inline short Clamp16(int value)
{
if (value > SHRT_MAX)
return SHRT_MAX;
if (value < SHRT_MIN)
return SHRT_MIN;
return value;
}
void decode(uint8_t* src, int16_t* dst, ADPCMINFO* cxt, uint32_t samples)
{
short hist1 = cxt->yn1;
short hist2 = cxt->yn2;
short* coefs = cxt->coef;
int frameCount = DivideByRoundUp(samples, SAMPLES_PER_FRAME);
int samplesRemaining = samples;
for (int i = 0; i < frameCount; i++)
{
int predictor = GetHighNibble(*src);
int scale = 1 << GetLowNibble(*src++);
short coef1 = coefs[predictor * 2];
short coef2 = coefs[predictor * 2 + 1];
int samplesToRead = MIN(SAMPLES_PER_FRAME, samplesRemaining);
for (int s = 0; s < samplesToRead; s++)
{
int sample = s % 2 == 0 ? GetHighNibble(*src) : GetLowNibble(*src++);
sample = sample >= 8 ? sample - 16 : sample;
sample = (((scale * sample) << 11) + 1024 + (coef1 * hist1 + coef2 * hist2)) >> 11;
short finalSample = Clamp16(sample);
hist2 = hist1;
hist1 = finalSample;
*dst++ = finalSample;
}
samplesRemaining -= samplesToRead;
}
}
void getLoopContext(uint8_t* src, ADPCMINFO* cxt, uint32_t samples)
{
short hist1 = cxt->yn1;
short hist2 = cxt->yn2;
short* coefs = cxt->coef;
char ps = 0;
int frameCount = DivideByRoundUp(samples, SAMPLES_PER_FRAME);
int samplesRemaining = samples;
for (int i = 0; i < frameCount; i++)
{
ps = *src;
int predictor = GetHighNibble(*src);
int scale = 1 << GetLowNibble(*src++);
short coef1 = coefs[predictor * 2];
short coef2 = coefs[predictor * 2 + 1];
int samplesToRead = MIN(SAMPLES_PER_FRAME, samplesRemaining);
for (int s = 0; s < samplesToRead; s++)
{
int sample = s % 2 == 0 ? GetHighNibble(*src) : GetLowNibble(*src++);
sample = sample >= 8 ? sample - 16 : sample;
sample = (((scale * sample) << 11) + 1024 + (coef1 * hist1 + coef2 * hist2)) >> 11;
short finalSample = Clamp16(sample);
hist2 = hist1;
hist1 = finalSample;
}
samplesRemaining -= samplesToRead;
}
cxt->loop_pred_scale = ps;
cxt->loop_yn1 = hist1;
cxt->loop_yn2 = hist2;
}

View File

@@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
project(DspTool LANGUAGES C)
option(BUILD_SHARED_LIBS "Build as a Shared Object or DLL" OFF)
set(HEADERS common.h dsptool.h)
set(SOURCES math.c decode.c encode.c)
add_library(DspTool ${HEADERS} ${SOURCES})
add_library(DspTool::DspTool ALIAS DspTool)
target_include_directories(DspTool PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
set_property(TARGET DspTool PROPERTY C_STANDARD 99)
if (BUILD_SHARED_LIBS)
target_compile_definitions(DspTool PRIVATE BUILD_SHARED)
endif()
target_compile_options(DspTool PRIVATE
$<$<C_COMPILER_ID:AppleClang,Clang,GNU>:-Wall -Wextra -pedantic -Wno-unused-parameter>
$<$<C_COMPILER_ID:MSVC>:/Wall /wd4100>)

View File

@@ -0,0 +1,7 @@
#ifndef COMMON_H
#define COMMON_H
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif//COMMON_H

View File

@@ -0,0 +1,101 @@
/* (c) 2017 Alex Barney (MIT) */
#include <stdint.h>
#include "common.h"
#include "dsptool.h"
static inline uint8_t GetHighNibble(uint8_t value)
{
return value >> 4 & 0xF;
}
static inline uint8_t GetLowNibble(uint8_t value)
{
return value & 0xF;
}
static inline int16_t Clamp16(int value)
{
if (value > INT16_MAX)
return INT16_MAX;
if (value < INT16_MIN)
return INT16_MIN;
return (int16_t)value;
}
void decode(uint8_t* src, int16_t* dst, ADPCMINFO* cxt, uint32_t samples)
{
short hist1 = cxt->yn1;
short hist2 = cxt->yn2;
short* coefs = cxt->coef;
uint32_t frameCount = (samples + SAMPLES_PER_FRAME - 1) / SAMPLES_PER_FRAME;
uint32_t samplesRemaining = samples;
for (uint32_t i = 0; i < frameCount; i++)
{
int predictor = GetHighNibble(*src);
int scale = 1 << GetLowNibble(*src++);
short coef1 = coefs[predictor * 2];
short coef2 = coefs[predictor * 2 + 1];
uint32_t samplesToRead = MIN(SAMPLES_PER_FRAME, samplesRemaining);
for (uint32_t s = 0; s < samplesToRead; s++)
{
int sample = (s & 0x1)
? GetLowNibble(*src++)
: GetHighNibble(*src);
sample = sample >= 8 ? sample - 16 : sample;
sample = (scale * sample) << 11;
sample = (sample + 1024 + (coef1 * hist1 + coef2 * hist2)) >> 11;
short finalSample = Clamp16(sample);
hist2 = hist1;
hist1 = finalSample;
*dst++ = finalSample;
}
samplesRemaining -= samplesToRead;
}
}
void getLoopContext(uint8_t* src, ADPCMINFO* cxt, uint32_t samples)
{
short hist1 = cxt->yn1;
short hist2 = cxt->yn2;
short* coefs = cxt->coef;
uint8_t ps = 0;
int frameCount = (int)((samples + SAMPLES_PER_FRAME - 1) / SAMPLES_PER_FRAME);
uint32_t samplesRemaining = samples;
for (int i = 0; i < frameCount; i++)
{
ps = *src;
int predictor = GetHighNibble(*src);
int scale = 1 << GetLowNibble(*src++);
short coef1 = coefs[predictor * 2];
short coef2 = coefs[predictor * 2 + 1];
uint32_t samplesToRead = MIN(SAMPLES_PER_FRAME, samplesRemaining);
for (uint32_t s = 0; s < samplesToRead; s++)
{
int sample = (s & 0x1)
? GetLowNibble(*src++)
: GetHighNibble(*src);
sample = sample >= 8 ? sample - 16 : sample;
sample = (scale * sample) << 11;
sample = (sample + 1024 + (coef1 * hist1 + coef2 * hist2)) >> 11;
short finalSample = Clamp16(sample);
hist2 = hist1;
hist1 = finalSample;
}
samplesRemaining -= samplesToRead;
}
cxt->loop_pred_scale = ps;
cxt->loop_yn1 = hist1;
cxt->loop_yn2 = hist2;
}

View File

@@ -1,4 +1,6 @@
#pragma once
#ifndef DSPTOOL_H
#define DSPTOOL_H
#ifdef __cplusplus
extern "C" {
#endif
@@ -9,10 +11,18 @@ extern "C" {
#define SAMPLES_PER_FRAME 14
#define NIBBLES_PER_FRAME 16
#ifdef COMPILING_DLL
#define DLLEXPORT __declspec(dllexport)
#if defined( _WIN32 ) || defined( __CYGWIN__ )
# ifdef BUILD_SHARED
# define DLLEXPORT __declspec(dllexport)
# elif defined( WHY_ARE_YOU_USING_THIS_AS_A_DLL )
# define DLLEXPORT __declspec(dllimport)
# else
# define DLLEXPORT
# endif
#elif __GNUC__ >= 4
# define DLLEXPORT __attribute__((visibility("default")))
#else
#define DLLEXPORT __declspec(dllimport)
# define DLLEXPORT
#endif
typedef struct
@@ -47,3 +57,5 @@ DLLEXPORT uint32_t getBytesForAdpcmInfo(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,41 +1,40 @@
/* (c) 2017 Alex Barney (MIT) */
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <float.h>
#include <string.h>
#include "common.h"
#include "dsptool.h"
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
/* Temporal Vector
* A contiguous history of 3 samples starting with
* 'current' and going 2 backwards
*/
typedef double tvec[3];
void correlateCoefs(int16_t* source, uint32_t samples, int16_t* coefsOut);
void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[8], const short coefsIn[8][2]);
static void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[8], const short coefsIn[8][2]);
void encode(int16_t* src, uint8_t* dst, ADPCMINFO* cxt, uint32_t samples)
{
int16_t* coefs = cxt->coef;
correlateCoefs(src, samples, coefs);
int32_t frameCount = samples / SAMPLES_PER_FRAME + (samples % SAMPLES_PER_FRAME != 0);
uint32_t frameCount = samples / SAMPLES_PER_FRAME + (samples % SAMPLES_PER_FRAME != 0);
int16_t* pcm = src;
uint8_t* adpcm = dst;
int16_t pcmFrame[SAMPLES_PER_FRAME + 2] = { 0 };
uint8_t adpcmFrame[BYTES_PER_FRAME] = { 0 };
for (int i = 0; i < frameCount; ++i, pcm += SAMPLES_PER_FRAME, adpcm += BYTES_PER_FRAME)
for (uint32_t i = 0; i < frameCount; ++i, pcm += SAMPLES_PER_FRAME, adpcm += BYTES_PER_FRAME)
{
int32_t sampleCount = MIN(samples - i * SAMPLES_PER_FRAME, SAMPLES_PER_FRAME);
uint32_t sampleCount = MIN(samples - i * SAMPLES_PER_FRAME, SAMPLES_PER_FRAME);
memset(pcmFrame + 2, 0, SAMPLES_PER_FRAME * sizeof(int16_t));
memcpy(pcmFrame + 2, pcm, sampleCount * sizeof(int16_t));
DSPEncodeFrame(pcmFrame, SAMPLES_PER_FRAME, adpcmFrame, (short(*)[2])&coefs[0]);
DSPEncodeFrame(pcmFrame, SAMPLES_PER_FRAME, adpcmFrame, (const short(*)[2])&coefs[0]);
pcmFrame[0] = pcmFrame[14];
pcmFrame[1] = pcmFrame[15];
@@ -49,7 +48,7 @@ void encode(int16_t* src, uint8_t* dst, ADPCMINFO* cxt, uint32_t samples)
cxt->yn2 = 0;
}
void InnerProductMerge(tvec vecOut, short pcmBuf[14])
static void InnerProductMerge(tvec vecOut, const short pcmBuf[14])
{
for (int i = 0; i <= 2; i++)
{
@@ -59,7 +58,7 @@ void InnerProductMerge(tvec vecOut, short pcmBuf[14])
}
}
void OuterProductMerge(tvec mtxOut[3], short pcmBuf[14])
static void OuterProductMerge(tvec mtxOut[3], const short pcmBuf[14])
{
for (int x = 1; x <= 2; x++)
for (int y = 1; y <= 2; y++)
@@ -70,12 +69,12 @@ void OuterProductMerge(tvec mtxOut[3], short pcmBuf[14])
}
}
bool AnalyzeRanges(tvec mtx[3], int* vecIdxsOut)
static bool AnalyzeRanges(tvec mtx[3], int* vecIdxsOut)
{
double recips[3];
double val, tmp, min, max;
/* Get greatest distance from zero */
// Get greatest distance from zero
for (int x = 1; x <= 2; x++)
{
val = MAX(fabs(mtx[x][1]), fabs(mtx[x][2]));
@@ -136,7 +135,7 @@ bool AnalyzeRanges(tvec mtx[3], int* vecIdxsOut)
}
}
/* Get range */
// Get range
min = 1.0e10;
max = 0.0;
for (int i = 1; i <= 2; i++)
@@ -154,7 +153,7 @@ bool AnalyzeRanges(tvec mtx[3], int* vecIdxsOut)
return false;
}
void BidirectionalFilter(tvec mtx[3], int* vecIdxs, tvec vecOut)
static void BidirectionalFilter(tvec mtx[3], const int* vecIdxs, tvec vecOut)
{
double tmp;
@@ -182,7 +181,7 @@ void BidirectionalFilter(tvec mtx[3], int* vecIdxs, tvec vecOut)
vecOut[0] = 1.0;
}
bool QuadraticMerge(tvec inOutVec)
static bool QuadraticMerge(tvec inOutVec)
{
double v0, v1, v2 = inOutVec[2];
double tmp = 1.0 - (v2 * v2);
@@ -199,7 +198,7 @@ bool QuadraticMerge(tvec inOutVec)
return fabs(v1) > 1.0;
}
void FinishRecord(tvec in, tvec out)
static void FinishRecord(tvec in, tvec out)
{
for (int z = 1; z <= 2; z++)
{
@@ -213,7 +212,7 @@ void FinishRecord(tvec in, tvec out)
out[2] = in[2];
}
void MatrixFilter(tvec src, tvec dst)
static void MatrixFilter(const tvec src, tvec dst)
{
tvec mtx[3];
@@ -237,7 +236,7 @@ void MatrixFilter(tvec src, tvec dst)
}
}
void MergeFinishRecord(tvec src, tvec dst)
static void MergeFinishRecord(const tvec src, tvec dst)
{
tvec tmp;
double val = src[0];
@@ -265,7 +264,7 @@ void MergeFinishRecord(tvec src, tvec dst)
FinishRecord(tmp, dst);
}
double ContrastVectors(tvec source1, tvec source2)
static double ContrastVectors(const tvec source1, const tvec source2)
{
double val = (source2[2] * source2[1] + -source2[1]) / (1.0 - source2[2] * source2[2]);
double val1 = (source1[0] * source1[0]) + (source1[1] * source1[1]) + (source1[2] * source1[2]);
@@ -274,7 +273,7 @@ double ContrastVectors(tvec source1, tvec source2)
return val1 + (2.0 * val * val2) + (2.0 * (-source2[1] * val + -source2[2]) * val3);
}
void FilterRecords(tvec vecBest[8], int exp, tvec records[], int recordCount)
static void FilterRecords(tvec vecBest[8], int exp, tvec records[], int recordCount)
{
tvec bufferList[8];
@@ -323,8 +322,8 @@ void FilterRecords(tvec vecBest[8], int exp, tvec records[], int recordCount)
void correlateCoefs(int16_t* source, uint32_t samples, int16_t* coefsOut)
{
int numFrames = (samples + 13) / 14;
int frameSamples;
uint32_t numFrames = (samples + 13) / 14;
uint32_t frameSamples;
short* blockBuffer = (short*)calloc(sizeof(short), 0x3800);
short pcmHistBuffer[2][14] = { 0 };
@@ -340,29 +339,29 @@ void correlateCoefs(int16_t* source, uint32_t samples, int16_t* coefsOut)
tvec vecBest[8];
/* Iterate though 1024-block frames */
for (int x = samples; x > 0;)
// Iterate though 1024-block frames
for (uint32_t x = samples; x > 0;)
{
if (x > 0x3800) /* Full 1024-block frame */
if (x > 0x3800) // Full 1024-block frame
{
frameSamples = 0x3800;
x -= 0x3800;
}
else /* Partial frame */
else // Partial frame
{
/* Zero lingering block samples */
// Zero lingering block samples
frameSamples = x;
for (int z = 0; z < 14 && z + frameSamples < 0x3800; z++)
blockBuffer[frameSamples + z] = 0;
x = 0;
}
/* Copy (potentially non-frame-aligned PCM samples into aligned buffer) */
// Copy (potentially non-frame-aligned PCM samples into aligned buffer)
memcpy(blockBuffer, source, frameSamples * sizeof(short));
source += frameSamples;
for (int i = 0; i < frameSamples;)
for (uint32_t i = 0; i < frameSamples;)
{
for (int z = 0; z < 14; z++)
pcmHistBuffer[0][z] = pcmHistBuffer[1][z];
@@ -416,7 +415,7 @@ void correlateCoefs(int16_t* source, uint32_t samples, int16_t* coefsOut)
FilterRecords(vecBest, exp, records, recordCount);
}
/* Write output */
// Write output
for (int z = 0; z < 8; z++)
{
double d;
@@ -433,12 +432,12 @@ void correlateCoefs(int16_t* source, uint32_t samples, int16_t* coefsOut)
coefsOut[z * 2 + 1] = (d < -32768.0) ? (short)-32768 : (short)lround(d);
}
/* Free memory */
// Free memory
free(records);
free(blockBuffer);
}
/* Make sure source includes the yn values (16 samples total) */
// Make sure source includes the yn values (16 samples total)
void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[8], const short coefsIn[8][2])
{
int inSamples[8][16];
@@ -449,32 +448,32 @@ void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[
int scale[8];
double distAccum[8];
/* Iterate through each coef set, finding the set with the smallest error */
// Iterate through each coef set, finding the set with the smallest error
for (int i = 0; i < 8; i++)
{
int v1, v2, v3;
int distance, index;
/* Set yn values */
// Set yn values
inSamples[i][0] = pcmInOut[0];
inSamples[i][1] = pcmInOut[1];
/* Round and clamp samples for this coef set */
// Round and clamp samples for this coef set
distance = 0;
for (int s = 0; s < sampleCount; s++)
{
/* Multiply previous samples by coefs */
// Multiply previous samples by coefs
inSamples[i][s + 2] = v1 = ((pcmInOut[s] * coefsIn[i][1]) + (pcmInOut[s + 1] * coefsIn[i][0])) / 2048;
/* Subtract from current sample */
// Subtract from current sample
v2 = pcmInOut[s + 2] - v1;
/* Clamp */
// Clamp
v3 = (v2 >= 32767) ? 32767 : (v2 <= -32768) ? -32768 : v2;
/* Compare distance */
// Compare distance
if (abs(v3) > abs(distance))
distance = v3;
}
/* Set initial scale */
// Set initial scale
for (scale[i] = 0; (scale[i] <= 12) && ((distance > 7) || (distance < -8)); scale[i]++, distance /= 2)
{
}
@@ -488,14 +487,14 @@ void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[
for (int s = 0; s < sampleCount; s++)
{
/* Multiply previous */
// Multiply previous
v1 = ((inSamples[i][s] * coefsIn[i][1]) + (inSamples[i][s + 1] * coefsIn[i][0]));
/* Evaluate from real sample */
// Evaluate from real sample
v2 = (pcmInOut[s + 2] << 11) - v1;
/* Round to nearest sample */
// Round to nearest sample
v3 = (v2 > 0) ? (int)((double)v2 / (1 << scale[i]) / 2048 + 0.4999999f) : (int)((double)v2 / (1 << scale[i]) / 2048 - 0.4999999f);
/* Clamp sample and set index */
// Clamp sample and set index
if (v3 < -8)
{
if (index < (v3 = -8 - v3))
@@ -509,14 +508,14 @@ void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[
v3 = 7;
}
/* Store result */
// Store result
outSamples[i][s] = v3;
/* Round and expand */
// Round and expand
v1 = (v1 + ((v3 * (1 << scale[i])) << 11) + 1024) >> 11;
/* Clamp and store */
// Clamp and store
inSamples[i][s + 2] = v2 = (v1 >= 32767) ? 32767 : (v1 <= -32768) ? -32768 : v1;
/* Accumulate distance */
// Accumulate distance
v3 = pcmInOut[s + 2] - v2;
distAccum[i] += v3 * (double)v3;
}
@@ -537,25 +536,23 @@ void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[
}
}
/* Write converted samples */
// Write converted samples
for (int s = 0; s < sampleCount; s++)
pcmInOut[s + 2] = inSamples[bestIndex][s + 2];
pcmInOut[s + 2] = (short)inSamples[bestIndex][s + 2];
/* Write ps */
// Write ps
adpcmOut[0] = (char)((bestIndex << 4) | (scale[bestIndex] & 0xF));
/* Zero remaining samples */
// Zero remaining samples
for (int s = sampleCount; s < 14; s++)
outSamples[bestIndex][s] = 0;
/* Write output samples */
// Write output samples
for (int y = 0; y < 7; y++)
{
adpcmOut[y + 1] = (char)((outSamples[bestIndex][y * 2] << 4) | (outSamples[bestIndex][y * 2 + 1] & 0xF));
}
}
void encodeFrame(int16_t* src, uint8_t* dst, int16_t* coefs, uint8_t one)
{
DSPEncodeFrame(src, 14, dst, (short(*)[2])&coefs[0]);
DSPEncodeFrame(src, 14, dst, (const short(*)[2])&coefs[0]);
}

View File

@@ -1,3 +1,5 @@
/* (c) 2017 Alex Barney (MIT) */
#include "dsptool.h"
uint32_t getBytesForAdpcmBuffer(uint32_t samples)
@@ -9,7 +11,7 @@ uint32_t getBytesForAdpcmBuffer(uint32_t samples)
return frames * BYTES_PER_FRAME;
}
uint32_t getBytesForAdpcmInfo()
uint32_t getBytesForAdpcmInfo(void)
{
return sizeof(ADPCMINFO);
}
@@ -21,9 +23,7 @@ uint32_t getBytesForAdpcmSamples(uint32_t samples)
uint32_t extraSamples = samples % SAMPLES_PER_FRAME;
if (extraSamples)
{
extraBytes = (extraSamples / 2) + (extraSamples % 2) + 1;
}
return BYTES_PER_FRAME * frames + extraBytes;
}
@@ -44,8 +44,8 @@ uint32_t getBytesForPcmSamples(uint32_t samples)
uint32_t getNibbleAddress(uint32_t samples)
{
int frames = samples / SAMPLES_PER_FRAME;
int extraSamples = samples % SAMPLES_PER_FRAME;
uint32_t frames = samples / SAMPLES_PER_FRAME;
uint32_t extraSamples = samples - (frames * SAMPLES_PER_FRAME);
return NIBBLES_PER_FRAME * frames + extraSamples + 2;
}
@@ -53,7 +53,7 @@ uint32_t getNibbleAddress(uint32_t samples)
uint32_t getNibblesForNSamples(uint32_t samples)
{
uint32_t frames = samples / SAMPLES_PER_FRAME;
uint32_t extraSamples = samples % SAMPLES_PER_FRAME;
uint32_t extraSamples = samples - (frames * SAMPLES_PER_FRAME);
uint32_t extraNibbles = extraSamples == 0 ? 0 : extraSamples + 2;
return NIBBLES_PER_FRAME * frames + extraNibbles;
@@ -62,7 +62,7 @@ uint32_t getNibblesForNSamples(uint32_t samples)
uint32_t getSampleForAdpcmNibble(uint32_t nibble)
{
uint32_t frames = nibble / NIBBLES_PER_FRAME;
uint32_t extraNibbles = nibble % NIBBLES_PER_FRAME;
uint32_t extraNibbles = nibble - (frames * NIBBLES_PER_FRAME);
uint32_t samples = SAMPLES_PER_FRAME * frames;
return samples + extraNibbles - 2;