I always planned to support audio with 24bit values in my Arduino Audio Tools library, but I never actually tested the functionality and so far I did not have a clear understanding of how these values would need to be represented. To be prepared I already provided a draft implementation of the int24_t data type, but there were some misunderstandings, that have been corrected now.

First we use the int24_t data type as you would expect. Here is an example Arduino sketch:

#include "Arduino.h"
#include "AudioTools.h"

I2SStream out;
SineWaveGenerator<int24_t> sine_wave;               
GeneratedSoundStream<int24_t> in_stream(sine_wave); 
StreamCopy copier(out, in_stream);                  

void setup(){
  Serial.begin(115200);
  AudioLogger::instance().begin(Serial, AudioLogger::Warning);

  auto cfg = out.defaultConfig();
  cfg.bits_per_sample = 24;
  out.begin(cfg);
  sine_wave.begin(cfg, N_B4);
  in_stream.begin(cfg);
}


void loop(){
  copier.copy();
}

No surprises so far: we generate 24bit samples (using int24_t) and specify the output to be 24 bits.
Here are the details on how int24_t is implemented:

  • Unlike the name might suggest, the values are stored in a int32_t, so it is 4 bytes wide.
  • The value range is from -8388608 to 8388607, so values outside of this range will need to be clipped.
  • I2S only considers the first 3 bytes and the last byte on the right will be ignored: So I am storing the value in a int32_t internally, but I shift the values by one byte to the left.
  • When casting an array of int24_t to a uint8_t*, we will automatically get the right representation.
  • However when converting an individual int24_t value to other data types, I needed to shift the value back by one byte to the right to get the correct original values.

Here is the current int24_t implementation which is part of the AudioTools project.

We can also visually test the result, by sending the output to CsvStreamout(Serial);
This gives:

0, 0
588736, 588736
1174569, 1174569
1754609, 1754609
2325996, 2325996
2885912, 2885912
3431595, 3431595
3960355, 3960355
4469584, 4469584
4956769, 4956769
5419510, 5419510
5855522, 5855522
6262658, 6262658
6638906, 6638906
6982415, 6982415
7291488, 7291488
7564601, 7564601
7800408, 7800408
7997746, 7997746
8155641, 8155641
8273315, 8273315
8350187, 8350187
8385879, 8385879
8380214, 8380214
8333219, 8333219
8245128, 8245128
8116374, 8116374
7947593, 7947593
7739616, 7739616
7493469, 7493469
7210366, 7210366
6891705, 6891705
6539055, 6539055
6154156, 6154156
5738908, 5738908
5295356, 5295356
4825688, 4825688
4332221, 4332221
3817391, 3817391
3283733, 3283733
2733880, 2733880
2170546, 2170546
1596506, 1596506
1014593, 1014593
427675, 427675
-161348, -161348
-749579, -749579
-1334113, -1334113
-1912066, -1912066
-2480591, -2480591
-3036882, -3036882
-3578196, -3578196
-4101861, -4101861
-4605300, -4605300
-5086026, -5086026
-5541667, -5541667
-5969981, -5969981
-6368850, -6368850
-6736312, -6736312
-7070551, -7070551
-7369920, -7369920
-7632944, -7632944
-7858323, -7858323
-8044948, -8044948
-8191897, -8191897
-8298445, -8298445
-8364068, -8364068
-8388442, -8388442
-8371446, -8371446
-8313165, -8313165
-8213886, -8213886
-8074098, -8074098
-7894490, -7894490
-7675949, -7675949
-7419553, -7419553
-7126564, -7126564
-6798431, -6798431
-6436768, -6436768
-6043363, -6043363
-5620153, -5620153
-5169224, -5169224
-4692804, -4692804
-4193241, -4193241
-3672995, -3672995
-3134638, -3134638
-2580821, -2580821
-2014273, -2014273
-1437795, -1437795
-854227, -854227
-266441, -266441
322649, 322649
910155, 910155
1493171, 1493171
2068824, 2068824
2634274, 2634274
3186732, 3186732
3723474, 3723474
4241853, 4241853
4739313, 4739313
5213399, 5213399
5661775, 5661775
6082228, 6082228
6472685, 6472685
6831221, 6831221
7156067, 7156067
7445622, 7445622
7698457, 7698457
7913326, 7913326
8089168, 8089168
8225117, 8225117
8320502, 8320502
8374853, 8374853
8387901, 8387901
8359583, 8359583
8290037, 8290037
8179608, 8179608
8028838, 8028838
7838473, 7838473
7609450, 7609450
7342900, 7342900
7040137, 7040137
6702653, 6702653
6332114, 6332114
5930348, 5930348
5499334, 5499334
5041198, 5041198
4558200, 4558200
4052724, 4052724
3527260, 3527260
2984401, 2984401
2426824, 2426824
1857278, 1857278
1278572, 1278572
693560, 693560
105130, 105130
-483820, -483820
-1070384, -1070384
-1651668, -1651668
-2224808, -2224808
-2786976, -2786976
-3335399, -3335399
-3867371, -3867371
-4380273, -4380273
-4871571, -4871571
-5338844, -5338844
-5779787, -5779787
-6192227, -6192227
-6574128, -6574128
-6923606, -6923606
-7238939, -7238939
-7518573, -7518573
-7761127, -7761127
-7965406, -7965406
-8130400, -8130400
-8255298, -8255298
-8339483, -8339483
-8382540, -8382540
-8384257, -8384257
-8344624, -8344624
-8263839, -8263839
-8142299, -8142299
-7980602, -7980602
-7779548, -7779548
-7540128, -7540128
-7263520, -7263520
-6951093, -6951093
-6604382, -6604382
-6225103, -6225103
-5815124, -5815124
-5376463, -5376463
-4911289, -4911289
-4421895, -4421895
-3910689, -3910689
-3380201, -3380201
-2833043, -2833043
-2271909, -2271909
-1699574, -1699574
-1118858, -1118858
-532619, -532619
56240, 56240
644824, 644824

This confirms that we get the result in the expected range.

ps. If you don’t want to use the int24_t data type, you can just use the int32_t data type instead and provide audio with 32 bits resulution. Then I2S will just consider the first 3 bytes and ignores the last 8 bits…


0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *