[PD] convert signal to 16bit stream

Roman Haefeli reduzent at gmail.com
Wed Nov 23 10:59:25 CET 2016

Hey all

Thanks for your submissions, Cyrille and Patrice. I put my 4 versions
and yours into a single patch to make it easy for comparing. It turns
out I'm not clearly in favor of any of them. All work fine and none is
perfect. In netpd, I went for table_lookup, however, it later turned
out that CPU wise, it's not that significantly faster than the others
and may not justify to use 2x4x65536 (which is a half MB!) of memory.

All of them are significantly faster than the message based version,
which is not that surprising.

Cyrilly, I think the table_lookup variant is what you described in your

It turns out that the difficult part is to find a way to implement an
[int~] with Pd-vanilla objects. Once, you have an [int~], you have a
[div~], and when you have [div~], you have a [mod~]. However, making a
good [int~] is not that trivial. One can make one with [wrap~], but it
exhibits the strange behaviour that it outputs '1' with '0' as input.
To work-around that, I add an integer constant to the input of [wrap~]
so that its input is always greater than 0. But because we're dealing
with floating point numbers, the fractional part of [wrap~] output is
less precise than the fractional part of its input (before constant was
added), which leads to rounding errors.

uint8_table uses a pre-computed table with values from 0 to 255, which
can be used as [int~] for said range.

float_rounding implements an [int~] by adding (and subsequently
subtracting) a constant which is high enough so that the fractional
part of the floating point number disappears. This approach might be
interesting for the purpose of this exercise, but it shoudln't be used.
It would break in an environment with a different floating point number

Cyrille Henry's approach assumes the receiving side automatically wraps
negative numbers around. It turns out to be true for the object classes
I'm interested in ([packOSC], [tcpclient], [netsend -b]), so his
version is quite clean and because of the lack of implementing another
[mod], it uses less arithmetic operations than my 'wrap' approach. It
totally lacks divisions. Thumbs up!

Patrice Colet's version uses [expr~] for some parts, which is fine, I
think. Somehow, for positive inputs the LSB is always higher by one
compared to the others. This leads to even more severe side effect for
input 1: 127 0 (should be 127 255).

Please share your opinions. I now think Cyrille's version is the best.


On Tue, 2016-11-08 at 12:06 +0100, cyrille henry wrote:
> hello,
> in your patch, the input signal is truncated, so strange things
> append near 0.
> I think rounding to inferior value will gives better result.
> here is a version done with 2 wrap~.
> the result for negative number is a bit different than in your
> example for 2 reason :
> - it round to inferior value and not truncate the input.
> - it return negative int, but in uint8 : 255 and -1 are the same
> number anyhow.
> sometimes rounding error result in 1 being 0.9999. So i guess this
> patch is useless.
> The other easy solution I can think of is using 2 tables with 65K
> point each, and reading the tables with tabread~.
> it is easy to populate the table with the value you want.
> sorry, i don't have time to provide a patch.
> cheers
> Cyrille
> Le 07/11/2016 à 16:24, Roman Haefeli a écrit :
> > 
> > Hi all
> > 
> > In order to store audio data more efficiently in netpd presets and
> > also
> > to transmit live audio through OSC, I'm thinking of ways to convert
> > an
> > signal to a 16-bit stream represented as two signals, one for each
> > byte, the first for MSB and the second for LSB. I already came up
> > with
> > a few solutions, but I'm not totally happy with any of them because
> > they are not very efficient or/and have strange edge cases. It
> > turns
> > out what seems a simple task is a bit more complex and probably has
> > quiet a few totally different solutions.
> > 
> > I would be interested to see with what solutions people come up
> > with.
> > Consider it a puzzle, a brain teaser (in case you're done writing
> > your
> > paper for pdcon and need some distraction).
> > 
> > Requirements:
> >  * It must be done in signal domain (I was doing it in message
> > domain
> >    yet, but performance is obviously bad)
> >  * Only vanilla objects are allowed.
> >  * Input is in the range -1 to 1. Input outside this range should
> > be
> >    clipped and not wrapped around.
> >  * Output is two signals, each consisting of an integer value
> > between
> >    0 and 255
> >  * The two bytes represent a 16-bit _signed_ integer
> > 
> > You can compare your output with the message version in attached
> > patch.
> > If this generates interest and makes some people participate, I'll
> > disclose my solutions after people submitted their solutions.
> > 
> > 
> > 
> > _______________________________________________
> > Pd-list at lists.iem.at mailing list
> > UNSUBSCRIBE and account-management -> https://lists.puredata.info/l
> > istinfo/pd-list
> > 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 16bit-converter-challenge.pd
Type: text/x-pd-l2ork
Size: 11698 bytes
Desc: not available
URL: <http://lists.puredata.info/pipermail/pd-list/attachments/20161123/f5af19ef/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: This is a digitally signed message part
URL: <http://lists.puredata.info/pipermail/pd-list/attachments/20161123/f5af19ef/attachment.sig>

More information about the Pd-list mailing list