MarkBeauchene
Posts: 23
Joined: Sat Nov 04, 2017 6:40 pm

ALSA Programming

Fri Feb 23, 2018 6:22 pm

I can nicely output a sine wave with the RPI using ALSA as long as the samples are 1 channel, 8 bit. When I try 16 bit or 2 channels it isn't pretty.

Here are the 8 bit details:
if ((err = snd_pcm_set_params(handle, SND_PCM_FORMAT_U8, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 48000, 1, 100000 ) ) < 0)
{

unsigned char buffer [ 96 ]; /* samples to play */

int tempint = 255 * sin ( baseVal [ keyPlaying ] * keyPos );
buffer[innr] = tempint & 0xff;

Here is my best guess (doesn't work) at 16 bit, one channel:
if ((err = snd_pcm_set_params(handle, SND_PCM_FORMAT_U16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 48000, 1, 100000 ) ) < 0)

unsigned char buffer [ 2 * 96 ]; /* samples to play */

int tempint = 37763 * sin ( baseVal [ keyPlaying ] * keyPos );
buffer[innr + 1] = ( tempint % 256 ) & 0xff;
buffer[innr] = ( tempint / 256 ) & 0xff;

Anyone see what I am doing wrong?

Additionally, to play silence in 8 bit (works great) I use:

for ( innr = 0; innr < sizeof ( buffer ); innr++ )
{
buffer[innr] = 0 & 0xff;
}

But in 16 bit there is a tone output:
for ( innr = 0; innr < sizeof ( buffer ); innr++ )
{
buffer[innr] = 0 & 0xff;
}

The ALSA site has tons of info, but I think I need "ALSA for Dummies"

Mark

LdB
Posts: 909
Joined: Wed Dec 07, 2016 2:29 pm

Re: ALSA Programming

Sat Feb 24, 2018 2:28 am

Yes you have 16bit issue here

Code: Select all

int tempint = 37763 * sin ( baseVal [ keyPlaying ] * keyPos );
I am also guessing 37763 is supposed to be 65535 being a full 16 bit range

Then you store them little endian

Code: Select all

buffer[innr + 1] = ( tempint % 256 ) & 0xff;
buffer[innr] = ( tempint / 256 ) & 0xff;
Consider the other endian :-)

Code: Select all

buffer[innr] = ( tempint % 256 ) & 0xff;
buffer[innr+1] = ( tempint / 256 ) & 0xff;
The fact this makes noise as you commented
But in 16 bit there is a tone output:
for ( innr = 0; innr < sizeof ( buffer ); innr++ )
{
buffer[innr] = 0 & 0xff;
}
Probably tells you that you can't do 8 bit writes

Okay so how do we fix this
I am going to make a suggestion you google stdint.h the C/C++ defined bit length unit
using int16_t makes life a whole lot easier

I will modify your code to use stdint.h and it will then look exactly like the 8 bit code

Code: Select all

#define <stdint.h>
int16_t [96 ]; /* samples to play */

int16_t tempint = 65535 * sin ( baseVal [ keyPlaying ] * keyPos );
buffer[innr] = tempint;

for ( innr = 0; innr < sizeof ( buffer ); innr++ )
{
buffer[innr] = 0;
}
If you want your 8 bit code in the same way

Code: Select all

#define <stdint.h>
int8_t [96 ]; /* samples to play */

int8_t tempint = 255 * sin ( baseVal [ keyPlaying ] * keyPos );
buffer[innr] = tempint;

User avatar
PeterO
Posts: 4294
Joined: Sun Jul 22, 2012 4:14 pm

Re: ALSA Programming

Sat Feb 24, 2018 8:18 am

LdB wrote:
Sat Feb 24, 2018 2:28 am
I am going to make a suggestion you google stdint.h the C/C++ defined bit length unit
using int16_t makes life a whole lot easier
I will modify your code to use stdint.h and it will then look exactly like the 8 bit code
+1
PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),Aeromodelling,1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

MarkBeauchene
Posts: 23
Joined: Sat Nov 04, 2017 6:40 pm

Re: ALSA Programming

Sat Feb 24, 2018 8:29 am

Thanks. I’ll look into into this in the morning. I just found I needed to make a change in the 8 bit code. The value needs to be
127 + 127* sin (.....). This way the values will be 0 to 254. It sounds way better.

User avatar
PeterO
Posts: 4294
Joined: Sun Jul 22, 2012 4:14 pm

Re: ALSA Programming

Sat Feb 24, 2018 8:39 am

You could also have done it by changing
SND_PCM_FORMAT_U8
to
SND_PCM_FORMAT_S8
and
int tempint = 255 * sin ( baseVal [ keyPlaying ] * keyPos );
to
int tempint = 127 * sin ( baseVal [ keyPlaying ] * keyPos );

BUT ISTR that might depend on the sound device having to support signed samples (and not all of them do that). I can't remember if the alsa code will do the conversion on the fly for you..

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),Aeromodelling,1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

blackshard83
Posts: 77
Joined: Fri Jan 10, 2014 8:31 am

Re: ALSA Programming

Mon Feb 26, 2018 8:28 am

PeterO wrote:
Sat Feb 24, 2018 8:39 am
BUT ISTR that might depend on the sound device having to support signed samples (and not all of them do that). I can't remember if the alsa code will do the conversion on the fly for you..
AFAIK signed 16 bit integers are the standard for 16 bit samples

MarkBeauchene
Posts: 23
Joined: Sat Nov 04, 2017 6:40 pm

Re: ALSA Programming

Wed Feb 28, 2018 11:28 pm

In case anyone has been following this - This RPI does have the equivalent of a sound card built in, and the ALSA objects are great. I have now programmed a synth with 8 note polyphony that generates a very acceptable organ, still in just 8 bits. The Linux system made connecting to a MIDI keyboard very easy as well and C is a very reasonable language. (I did have some experience with C++ Builder several years ago.)

Thanks to the forum members who "held my hand". Perhaps one day I'll write up a tutorial on how this has come together that could prove helpful to others.

Return to “C/C++”