Skip to content

Commit a061339

Browse files
author
mpg123 GitHub bot
committed
Merge remote-tracking branch 'mpg123/master' into master-with-github-ci
2 parents 22853bc + 4378234 commit a061339

7 files changed

Lines changed: 146 additions & 87 deletions

File tree

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
------
33
- libout123: Add a safeguard to ensure variable-length records from buffer
44
communication are always zero-terminated.
5+
- libsyn123: Use union work buffer to avoid casts that may look like breaking
6+
strict aliasing.
57

68
1.33.4
79
------

src/libsyn123/geiger.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
static void white_generator(syn123_handle *sh, int samples)
2525
{
2626
for(int i=0; i<samples; ++i)
27-
sh->workbuf[1][i] = 2*rand_xorshift32(&sh->seed);
27+
sh->workbuf.f64[1][i] = 2*rand_xorshift32(&sh->seed);
2828
}
2929

3030
int attribute_align_arg
@@ -234,11 +234,11 @@ static void geiger_generator(syn123_handle *sh, int samples)
234234
{
235235
struct geigerspace *gs = sh->handle;
236236
for(int i=0; i<samples; ++i)
237-
sh->workbuf[1][i] = speaker( gs
237+
sh->workbuf.f64[1][i] = speaker( gs
238238
, discharge_force(gs, (rand_xorshift32(&sh->seed)+0.5)>gs->thres) );
239239
// Soft clipping as speaker property. It can only move so far.
240240
// Of course this could be produced by a nicely nonlinear force, too.
241-
syn123_soft_clip( sh->workbuf[1], MPG123_ENC_FLOAT_64, samples
241+
syn123_soft_clip( sh->workbuf.f64[1], MPG123_ENC_FLOAT_64, samples
242242
, 1., 0.1, NULL );
243243
}
244244

src/libsyn123/libsyn123.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ static void wave_add_buffer( double outbuf[bufblock], size_t samples
365365
static void silence_generator(syn123_handle *sh, int samples)
366366
{
367367
for(int i=0; i<samples; ++i)
368-
sh->workbuf[1][i] = 0;
368+
sh->workbuf.f64[1][i] = 0;
369369
}
370370

371371
// Clear the handle of generator data structures.
@@ -395,11 +395,11 @@ static void wave_generator(syn123_handle *sh, int samples)
395395
{
396396
/* Initialise to zero amplitude. */
397397
for(int i=0; i<samples; ++i)
398-
sh->workbuf[1][i] = 1;
398+
sh->workbuf.f64[1][i] = 1;
399399
/* Add individual waves. */
400400
for(size_t c=0; c<sh->wave_count; ++c)
401-
wave_add_buffer( sh->workbuf[1], samples, sh->fmt.rate, sh->waves+c
402-
, sh->workbuf[0] );
401+
wave_add_buffer( sh->workbuf.f64[1], samples, sh->fmt.rate, sh->waves+c
402+
, sh->workbuf.f64[0] );
403403
}
404404

405405
/* Build internal table, allocate external table, convert to that one, */
@@ -625,11 +625,11 @@ static void sweep_generator(syn123_handle *sh, int samples)
625625
{
626626
struct syn123_sweep *sw = sh->handle;
627627
// Precompute phases into work buffer.
628-
sweep_phase(sh, 0, sh->workbuf[0], samples);
628+
sweep_phase(sh, 0, sh->workbuf.f64[0], samples);
629629
// Initialise output to zero amplitude and multiply by the wave.
630630
for(int i=0; i<samples; ++i)
631-
sh->workbuf[1][i] = 1.;
632-
evaluate_wave(sh->workbuf[1], samples, sw->wave.id, sh->workbuf[0]);
631+
sh->workbuf.f64[1][i] = 1.;
632+
evaluate_wave(sh->workbuf.f64[1], samples, sw->wave.id, sh->workbuf.f64[0]);
633633
// Advance.
634634
sw->i = (sw->i+samples) % (sw->d + sw->post);
635635
}
@@ -702,9 +702,9 @@ syn123_setup_sweep( syn123_handle* sh
702702
// The last phase served by the sweep, and the one after that that
703703
// tryly concludes the sweep (f==f2, not infinitesimally smaller).
704704
mdebug("computing endphase, with 2 points from %zu - 1 on", duration);
705-
sweep_phase(sh, duration-1, sh->workbuf[0], 2);
706-
double before_endphase = sh->workbuf[0][0];
707-
sw->endphase = sh->workbuf[0][1];
705+
sweep_phase(sh, duration-1, sh->workbuf.f64[0], 2);
706+
double before_endphase = sh->workbuf.f64[0][0];
707+
sw->endphase = sh->workbuf.f64[0][1];
708708
sw->post = 0; // Reset that again, only increasing if really needed.
709709
// The phase that would smoothly continue the sweep, one sample
710710
// after the last one.
@@ -895,22 +895,22 @@ syn123_read( syn123_handle *sh, void *dest, size_t dest_bytes )
895895
// Compute data into workbuf[1], possibly using workbuf[0]
896896
// in the process.
897897
// TODO for the future: Compute only in single precision if
898-
// it is enough.
898+
// it is enough. Right now generators always write to workbuf.f64[1].
899899
sh->generator(sh, block);
900900
// Convert to external format, mono. We are abusing workbuf[0] here,
901901
// because it is big enough.
902902
// The converter does not use workbuf if converting from float. Dither is
903903
// added on the fly.
904904
int err = syn123_conv(
905-
sh->workbuf[0], sh->fmt.encoding, sizeof(sh->workbuf[0])
906-
, sh->workbuf[1], MPG123_ENC_FLOAT_64, sizeof(double)*block
905+
sh->workbuf.c[0], sh->fmt.encoding, sizeof(sh->workbuf.c[0])
906+
, sh->workbuf.c[1], MPG123_ENC_FLOAT_64, sizeof(double)*block
907907
, NULL, NULL, NULL );
908908
if(err)
909909
{
910910
debug1("conv error: %i", err);
911911
break;
912912
}
913-
syn123_mono2many( cdest, sh->workbuf[0]
913+
syn123_mono2many( cdest, sh->workbuf.c[0]
914914
, sh->fmt.channels, samplesize, block );
915915
cdest += framesize*block;
916916
dest_samples -= block;

src/libsyn123/pinknoise.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ static float GeneratePinkNoise( PinkNoise *pink )
122122
static void pink_generator(syn123_handle *sh, int samples)
123123
{
124124
for(int i=0; i<samples; ++i)
125-
sh->workbuf[1][i] = GeneratePinkNoise(sh->handle);
125+
sh->workbuf.f64[1][i] = GeneratePinkNoise(sh->handle);
126126
}
127127

128128
int attribute_align_arg

src/libsyn123/sampleconv.c

Lines changed: 81 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -189,23 +189,35 @@ syn123_soft_clip( void *buf, int encoding, size_t samples
189189
if(!mixenc || !mixframe || !inframe)
190190
return 0;
191191
// Use the whole workbuf, both halves.
192-
int mbufblock = 2*bufblock*sizeof(double)/mixframe;
192+
int mbufblock = sizeof(sh->workbuf)/mixframe;
193193
mdebug("mbufblock=%i (enc %i)", mbufblock, mixenc);
194194
while(samples)
195195
{
196196
int block = (int)smin(samples, mbufblock);
197-
int err = syn123_conv(
198-
sh->workbuf, mixenc, sizeof(sh->workbuf)
199-
, cbuf, encoding, inframe*block
200-
, NULL, NULL, NULL );
197+
int err = mixenc == MPG123_ENC_FLOAT_64
198+
? syn123_conv(
199+
sh->workbuf.f64, mixenc, sizeof(sh->workbuf.f64)
200+
, cbuf, encoding, inframe*block
201+
, NULL, NULL, NULL )
202+
: syn123_conv(
203+
sh->workbuf.f32, mixenc, sizeof(sh->workbuf.f32)
204+
, cbuf, encoding, inframe*block
205+
, NULL, NULL, NULL );
201206
if(!err)
202207
{
203-
clipped += syn123_soft_clip(sh->workbuf, mixenc, block, limit, width, NULL);
208+
clipped += mixenc == MPG123_ENC_FLOAT_64
209+
? syn123_soft_clip(sh->workbuf.f64, mixenc, block, limit, width, NULL)
210+
: syn123_soft_clip(sh->workbuf.f32, mixenc, block, limit, width, NULL);
204211
// No additional clipping can happen here.
205-
err = syn123_conv(
206-
cbuf, encoding, inframe*block
207-
, sh->workbuf, mixenc, mixframe*block
208-
, NULL, NULL, NULL );
212+
err = mixenc == MPG123_ENC_FLOAT_64
213+
? syn123_conv(
214+
cbuf, encoding, inframe*block
215+
, sh->workbuf.f64, mixenc, mixframe*block
216+
, NULL, NULL, NULL )
217+
: syn123_conv(
218+
cbuf, encoding, inframe*block
219+
, sh->workbuf.f32, mixenc, mixframe*block
220+
, NULL, NULL, NULL );
209221
}
210222
if(err)
211223
{
@@ -542,7 +554,7 @@ syn123_conv( void * MPG123_RESTRICT dst, int dst_enc, size_t dst_size
542554
if(!mixenc || !mixframe)
543555
return SYN123_BAD_CONV;
544556
// Use the whole workbuf, both halves.
545-
int mbufblock = 2*bufblock*sizeof(double)/mixframe;
557+
int mbufblock = sizeof(sh->workbuf)/mixframe;
546558
mdebug("mbufblock=%i (enc %i)", mbufblock, mixenc);
547559
// Abuse the handle workbuf for intermediate storage.
548560
size_t samples_left = samples;
@@ -555,16 +567,26 @@ syn123_conv( void * MPG123_RESTRICT dst, int dst_enc, size_t dst_size
555567
{
556568
int block = (int)smin(samples_left, mbufblock);
557569
size_t clipped_now = 0;
558-
int err = syn123_conv(
559-
sh->workbuf, mixenc, sizeof(sh->workbuf)
560-
, csrc, src_enc, srcframe*block
561-
, NULL, NULL, NULL );
570+
int err = mixenc == MPG123_ENC_FLOAT_64
571+
? syn123_conv(
572+
sh->workbuf.f64, mixenc, sizeof(sh->workbuf.f64)
573+
, csrc, src_enc, srcframe*block
574+
, NULL, NULL, NULL )
575+
: syn123_conv(
576+
sh->workbuf.f32, mixenc, sizeof(sh->workbuf.f32)
577+
, csrc, src_enc, srcframe*block
578+
, NULL, NULL, NULL );
562579
sh->do_dither = do_dither; // possibly dither now
563580
if(!err)
564-
err = syn123_conv(
565-
cdst, dst_enc, dstframe*block
566-
, sh->workbuf, mixenc, mixframe*block
567-
, NULL, &clipped_now, sh );
581+
err = mixenc == MPG123_ENC_FLOAT_64
582+
? syn123_conv(
583+
cdst, dst_enc, dstframe*block
584+
, sh->workbuf.f64, mixenc, mixframe*block
585+
, NULL, &clipped_now, sh )
586+
: syn123_conv(
587+
cdst, dst_enc, dstframe*block
588+
, sh->workbuf.f32, mixenc, mixframe*block
589+
, NULL, &clipped_now, sh );
568590
if(err)
569591
{
570592
mdebug("conv error: %i", err);
@@ -861,6 +883,38 @@ static void syn123_mix_f64( double * MPG123_RESTRICT dst, int dst_channels
861883
SYN123_MIX_FUNC(double)
862884
}
863885

886+
// Call with f64 or f32 for conversion mixer code piece.
887+
#define CONVMIX(fXX) \
888+
err = syn123_conv( \
889+
sh->workbuf.fXX[0], mixenc, sizeof(sh->workbuf.fXX[0]) \
890+
, csrc, src_enc, srcframe*block \
891+
, NULL, NULL, NULL ); \
892+
if(err) \
893+
goto mix_end; \
894+
/* Initialize to zero or convert from old output signal. */ \
895+
if(silence) \
896+
for(int i=0; i<block*dst_channels; ++i) \
897+
sh->workbuf.fXX[1][i] = 0.; \
898+
else \
899+
err = syn123_conv( \
900+
sh->workbuf.fXX[1], mixenc, sizeof(sh->workbuf.fXX[1]) \
901+
, cdst, dst_enc, dstframe*block \
902+
, NULL, NULL, NULL ); \
903+
/* Now mix one work buffer into the other. */ \
904+
if(err) \
905+
goto mix_end; \
906+
err = syn123_mix( sh->workbuf.fXX[1], mixenc, dst_channels \
907+
, sh->workbuf.fXX[0], mixenc, src_channels, mixmatrix, block \
908+
, 0, NULL, NULL ); \
909+
if(err) \
910+
goto mix_end; \
911+
/* And convert to the final output format. */ \
912+
err = syn123_conv( \
913+
cdst, dst_enc, dstframe*block \
914+
, sh->workbuf.fXX[1], mixenc, mixoutframe*block \
915+
, NULL, &clips_block, NULL );
916+
917+
864918
int attribute_align_arg
865919
syn123_mix( void * MPG123_RESTRICT dst, int dst_enc, int dst_channels
866920
, void * MPG123_RESTRICT src, int src_enc, int src_channels
@@ -926,7 +980,7 @@ syn123_mix( void * MPG123_RESTRICT dst, int dst_enc, int dst_channels
926980
goto mix_end;
927981
}
928982
// Mix from buffblock[0] to buffblock[1].
929-
int mbufblock = bufblock*sizeof(double)/mixframe;
983+
int mbufblock = sizeof(sh->workbuf)/2/mixframe;
930984
mdebug("mbufblock=%i (enc %i)", mbufblock, mixenc);
931985
// Need at least one sample per round to avoid endless loop.
932986
// Of course, we would prefer more, but it's your fault for
@@ -940,38 +994,15 @@ syn123_mix( void * MPG123_RESTRICT dst, int dst_enc, int dst_channels
940994
while(samples)
941995
{
942996
int block = (int)smin(samples, mbufblock);
943-
err = syn123_conv( sh->workbuf[0], mixenc, sizeof(sh->workbuf[0])
944-
, csrc, src_enc, srcframe*block
945-
, NULL, NULL, NULL );
946-
if(err)
947-
goto mix_end;
948-
// Initialize to zero or convert from old output signal.
949-
if(silence)
997+
size_t clips_block = 0;
998+
// The same logic for f64 and f32, just written explictly for buffer type clarity.
999+
if(mixenc == MPG123_ENC_FLOAT_64)
1000+
{
1001+
CONVMIX(f64)
1002+
} else
9501003
{
951-
if(mixenc == MPG123_ENC_FLOAT_32)
952-
for(int i=0; i<block*dst_channels; ++i)
953-
((float*)(sh->workbuf[1]))[i] = 0.;
954-
else
955-
for(int i=0; i<block*dst_channels; ++i)
956-
sh->workbuf[1][i] = 0.;
1004+
CONVMIX(f32)
9571005
}
958-
else
959-
err = syn123_conv( sh->workbuf[1], mixenc, sizeof(sh->workbuf[1])
960-
, cdst, dst_enc, dstframe*block
961-
, NULL, NULL, NULL );
962-
// Now mix one work buffer into the other.
963-
if(!err)
964-
err = syn123_mix( sh->workbuf[1], mixenc, dst_channels
965-
, sh->workbuf[0], mixenc, src_channels, mixmatrix, block
966-
, 0, NULL, NULL );
967-
if(err)
968-
goto mix_end;
969-
// And convert to the final output format.
970-
size_t clips_block = 0;
971-
err = syn123_conv(
972-
cdst, dst_enc, dstframe*block
973-
, sh->workbuf[1], mixenc, mixoutframe*block
974-
, NULL, &clips_block, NULL );
9751006
clips += clips_block;
9761007
if(err)
9771008
goto mix_end;

src/libsyn123/syn123_int.h

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,25 @@ struct syn123_struct
7979
// This is a set of two to accomodate x and y=function(x, y).
8080
// Working in blocks reduces function call overhead and gives
8181
// chance of vectorization.
82-
// This may also be used as buffer for data with output encoding,
83-
// exploiting the fact that double is the biggest data type we
84-
// handle, also with the biggest alignment.
85-
double workbuf[2][bufblock];
82+
// This may also be used as buffer for data with various encodings,
83+
// hence a union to express this in the nicest possible way. This storage
84+
// is used in a number of ways.
85+
// All members have to be the same size, utilizing the whole storage
86+
// block. Code using it assumes that sizeof(workbuf) gives the numbers
87+
// of bytes accessible via any member.
88+
union {
89+
double f64[2][bufblock];
90+
float f32[2][2*bufblock];
91+
uint32_t u32[2][2*bufblock];
92+
int32_t i32[2][2*bufblock];
93+
uint16_t u16[2][4*bufblock];
94+
int16_t i16[2][4*bufblock];
95+
uint8_t u8[2][8*bufblock];
96+
int8_t i8[2][8*bufblock];
97+
// Yes, again the same, to be overly explicit about type names.
98+
char c[2][8*bufblock];
99+
unsigned char uc[2][8*bufblock];
100+
} workbuf;
86101
struct mpg123_fmt fmt;
87102
int dither; // if dithering is activated for the handle
88103
int do_dither; // flag for recursive calls of syn123_conv()

src/libsyn123/volume.c

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,25 @@ double attribute_align_arg syn123_lin2db(double volume)
4747
}
4848

4949

50+
#define CONVAMP(fXX) \
51+
err = syn123_conv( \
52+
sh->workbuf.fXX, mixenc, sizeof(sh->workbuf.fXX) \
53+
, cbuf, encoding, inframe*block \
54+
, NULL, NULL, NULL ); \
55+
if(!err) \
56+
{ \
57+
err = syn123_amp( sh->workbuf.fXX, mixenc, block \
58+
, volume, offset, NULL, NULL ); \
59+
if(err) \
60+
return err; \
61+
err = syn123_conv( \
62+
cbuf, encoding, inframe*block \
63+
, sh->workbuf.fXX, mixenc, mixframe*block \
64+
, NULL, &clips_block, NULL ); \
65+
clips += clips_block; \
66+
}
67+
68+
5069
int attribute_align_arg
5170
syn123_amp( void* buf, int encoding, size_t samples
5271
, double volume, double offset, size_t *clipped, syn123_handle *sh )
@@ -94,22 +113,14 @@ syn123_amp( void* buf, int encoding, size_t samples
94113
while(samples)
95114
{
96115
int block = (int)smin(samples, mbufblock);
97-
int err = syn123_conv(
98-
sh->workbuf, mixenc, sizeof(sh->workbuf)
99-
, cbuf, encoding, inframe*block
100-
, NULL, NULL, NULL );
101-
if(!err)
116+
size_t clips_block = 0;
117+
int err = 0;
118+
if(mixenc == MPG123_ENC_FLOAT_64)
119+
{
120+
CONVAMP(f64)
121+
} else
102122
{
103-
err = syn123_amp( sh->workbuf, mixenc, block
104-
, volume, offset, NULL, NULL );
105-
if(err)
106-
return err;
107-
size_t clips_block = 0;
108-
err = syn123_conv(
109-
cbuf, encoding, inframe*block
110-
, sh->workbuf, mixenc, mixframe*block
111-
, NULL, &clips_block, NULL );
112-
clips += clips_block;
123+
CONVAMP(f32)
113124
}
114125
if(err)
115126
{

0 commit comments

Comments
 (0)