Category: C

How to fix sound on the Raspberry Pi

How to fix sound on the Raspberry Pi

Raspi-config for Raspberry PiFirst I modded the code that inits sound to this:

	int success=Mix_OpenAudio(44000, AUDIO_F32LSB, 2, 8192);
	if (success==-1 ) {

		LogError2("InitSetup failed to init audio because %s",Mix_GetError());
	}

That extra call to Mix_GetError() returns a string saying what the problem is and in this case I got

ALSA : Couldn’t find any hardware audio formats.

ALSA is short for Advanced Linux Sound Architecture and Wikipedia is very informative. It certainly put some perspective on it.

 

Also I found this article adds a lot more information.  What fixed it though was doing

sudo raspi-config

Then pressing enter on 1. System Options and then S2 Audio and selecting the headphones option. Simple as that. After that asteroids played the sounds as expected.

There’s a lesson here which is to use the functions provided, in this case calling the Mix_GetError() function to show errors.  I added it into the PlayASound() call to see why it was failing, and it stopped doing it, i.e. it worked with lots of explosions on screen. I suspect it was the sound configuration hadn’t been properly set which is an issue with Raspberry Pis apparently.

Raspberry Pi Sound issues- trying to fix it

Raspberry Pi Sound issues- trying to fix it

Loudpeaker
Image by OpenClipart-Vectors from Pixabay

In working through my Linux/Raspberry Pi eBook(Yes – the second eBook!), I’m up to the chapter where sounds are introduced using the SDL_mixer library. And I’ve hit two sets of problems.

It sometimes refuses to initialize the sound code.  This code below hits the LogError line:

	int success=Mix_OpenAudio(22050, AUDIO_S16LSB, 2, 8192);
	if (success==-1 ) {
		LogError("InitSetup failed to init audio");
	}

The other day it was working but not today. Now I have updated the Pi’s code (sudo apt update etc) but I wouldn’t have expected that to break it. I’ve been looking on the internet and find the whole thing a bit complicated.

I’ve got my Pi running 64-bit Raspberry Pi OS. I’ve changed the output device to headphones which plug into the headphone socket. If I run the VLC media player and tell it to play into the headphones, it will happily play the .wav files I’ve got for the asteroids game.

But if I run speaker-test, a terminal application with this command line

speaker-test -c2 -twav -l7 plughw:1,0

I get

speaker-test 1.2.4

Playback device is default
Stream parameters are 48000Hz, S16_LE, 2 channels
WAV file(s)
Setting of hwparams failed: Invalid argument

By running this command:

aplay -L

I got 71 lines of output but of these these below are the most important

output
hw:CARD=Headphones,DEV=0
    bcm2835 Headphones, bcm2835 Headphones

and the speaker-test command using the device parameter –Dhw:Headphones now worked. I’ve highlighted the bits in the aplay output needed to identify the device.

The new command  is

speaker-test -c2 -twav -l7 -Dhw:Headphones

I can now hear a female voice saying front left then front right a few times in my headphones.

So my Pi’s sound device is working; I just have to figure why SDL_mixer isn’t always. I’ll keep looking.

And the second problem which only occurs when the mixer is working, is when you play a lot of sounds. The PlayASound() function checks the result. On Windows it never had a problem but on Raspberry Pi, when you blow up a lot of asteroids say at one time, it plays a number of explosions then returns an error for each explosion after that. I think there’s only so many channels; that’s an easy fix; just ignore the error and return as if it succeeded.

A very useful Windows Utility in C

A very useful Windows Utility in C

ExplorerPatcher menuIf you use Windows 11 you’ll be aware of one or two issues with it; the file explorer popup menu needs a second click to take you to the Windows 10 menu with Copy, cut paste etc.

So I was pleased to discover explorer patcher which is a utility written in C that lets you get the Windows 10 right-click menu back as well as changing the File explorer right-click popup menu and a lot of other stuff.

It’s on GitHub and the authors are happy for you to look at the source code and submit improvements of your own.

If you want to see how to make changes to Windows etc in C, this is a great example.

Added to the C Code Links page.

PS. I use this and have found that after a Windows update, the right-click menu gets reset to the Windows 11. However just opening the explorer patcher settings and unticking then ticking the option for Disable the Windows 11 context menu on the File Explorer menu fixes it.

How to Configure Visual Studio Code for C/C++ development

How to Configure Visual Studio Code for C/C++ development

VS Code C/C++ extensionWhen I first started with VS Code on Linux, I found the C/C++ configuration somewhat confusing.  I blundered through, wasted a bit of time and got there in the end. After a gap of a couple of years I did the same again recently on Raspberry Pi. It’s clearer in my mind now so I thought I’d explain it here. This works for Ubuntu, Raspberry Pi OS and should for most other Linuxes. (Not that I’ve tried them all…)

We’ll start with you having already installed Clang (or GCC) and VS Code, and the C/C++ extension for VS Code (shown above). So make sure those are all done.

Start by defining a Folder for VS Code. VS code doesn’t use projects but it manages everything relative to the currently defined Folder.  It’ll ask you to open a folder initially. That’s where your source code etc will go. I created a folder called examples under my home folder and used that.

To compile anything C/C++ you also need two json files. These files are

  • tasks.json
  • c_cpp_properties.json

They are held in a hidden folder called .vscode in your current folder. Press F1 and you’ll see a popup menu. Type in C/C++ and you’ll see all the C/C++ items. Select C/C++: Edit Configurations (JSON). It’s highlighted below.

Vs Copde C++ menu

Now if you click that, and look in the folder examples you’ll see nothing but if you know how to view hidden files using the files utility (as shown below). Then you’ll see the folder .vscode.  On Raspberry Pi the file explorer always shows hidden files.

Show hidden files in files utility Now look in that folder and you’ll see c_cpp_properties.json.

Next we want tasks.json. On the Terminal menu, click the bottom item which is Configure Default Build Task

It’ll ask you to select the clang  build active task so click that and voila you now have tasks.json open in the editor.

Vs Code Configure Default Build Task

Build Active File

 

 

 

 

 

 

 

 

 

 

Now I’ve created the standard hello world file in the file hw.c.

#include <stdio.h>

int main() {
  printf("Hello world\n");
  return 0;
}

So just do Terminal/Run Build Task and it will have clang compile the currently opened file. If you get terminal failed to launch (exit code: -1) then it’s likely that your hello world source file was not the currently opened file in the editor. You can see which file is open because its tab is brightest.

Note that hw.c is brighter than tasks.json on the left. On the right, the open file is tasks.json and its tab is brighter.

Open file in VS Code

Tasks.json is open

So what are the json files for?

The c_cpp_properties.json lets you specify include file paths.  For instance if you have the SDL files installed, the include files are in /usr/include/SDL2

SDL2 include files

Note you can install SDL on linux by following these instructions.

The tasks.json file lets you specify which files are to be included and also linked.

Here I’ve just shown the args section from a tasks.json used to build SDL2 games.

	"args": [
		"-g",
		"${file}",
		"${workspaceFolder}/hr_time.c",
		"-o",
		"${fileDirname}/${fileBasenameNoExtension}",
		"-lSDL2",
		"-lSDL2_image",
		"-lSDL2_mixer",
		"-lm"
	],

The -g option includes files. The ${file} is the current opened file and {workspaceFolder{} specifies the current folder where the file hr_time.c (used for timing). The -l is for linking files and links SDL2, SDL2_image and SDL2_mixer.  The last -lm links math(s) code; technically the -l{name} flag tells the linker to link against lib{name}. So -lm links against libm, the c math library.

I know a fair bit of C but

I know a fair bit of C but

The letter C in fancy script
Image by Gordon Johnson from Pixabay

There are a lot of subtleties that you only pick up with experience.  I was pleased to find a blog entry by a bloke Tom M on “Everything I wish I knew when learning C” which is well worth a read.

I’m not going to copy anything from it except for this little snippet below one below. For the rest, you’ll have to read his blog post.

char signedness

All other integer types default to signed, but bare char can be signed or unsigned, depending on the platform.

As said char is an integer type but unless you are doing stuff like ++ or — when its value can overflow according to being signed or unsigned, it’s not really a problem. And unless you are writing code that runs on wildly differing platforms, you can probably safely assume that a char is the same as a byte and has 8 bits. On those other platforms, I’d suggest you read the answers to this Stackoverflow question.

Update to the Windows eBook

Update to the Windows eBook

Visual Studio configurationA reader asked me how to setup SDL2 for Windows given recent changes in SDL2. Specifically the files and libsdl projects have been moved from the libsdl.org website to GitHub. You can easily find SDL2 Image, Mixer, TTF etc.

However it can still be quite daunting setting up Visual Studio for SDL2. You have to download the specific files, then configure the project properties to specify the include paths for header files and then the lib files, both the path to them and identify the ones you want to use.

As I’m on my new PC, I bit the bullet and went through the process of setting it up. It took just over an hour to configure it.  I’ve put it into a PDF that’s a couple of pages long.

So the game works but only after I disabled the sound code; it was failing in the call to Mix_OpenAudio(). I think recent work on the SDL Mixer needs some work on my part. I need to sit down and look at the SDL Mixer page and figure out what’s failing. Once that’s done, I’ll update the files.

 

++/– Operators work on floats and doubles

++/– Operators work on floats and doubles

laptop computer with an editor
From Instant Images

No matter how much I use C there are still things I thought I knew but find out otherwise. The latest one is that you can use ++ or — on float and double variables.

Here for instance is a short nonsense program that I compiled and ran with Visual Studio on Windows. As you’#ll notice, it increments and decrements floats and a double.

The danger with using this is that you might get rounding errors. When I ran it on Windows, I didn’t which surprised me. I will have to try this on Linux.

#include <stdio.h>

void main()
{
    float c = 1.0f;
    float cin = 10000.0f;
    double d = 2.0;
    int i = 0;

    while (cin != c)
    {
        i++;
        cin = c;
        c--;
        d++;
    }
    printf("%i %e %e\n", i, c, d);
}
Mle – a small text editor in under 10,000 lines of code

Mle – a small text editor in under 10,000 lines of code

Mie text editorIf you’re into C, one of the most interesting applications you can write is a text editor. It demands ability to use pointers for storing the text efficiently and command handling and doing things like searching, handling Unicode.

It can be equally instructive reading code someone else has written and this case Mle, is a text editor in less than 10,000 lines of C. It’s also cross-platform apparently, though you’ll have to build it on the relevant platform.

It uses three other open source libraries, linked at the foot of the main page. They are uthash, termbox2 and PCRE2.

Everything and fsearch

Everything and fsearch

Everything File SearchI’m currently operating on a Linux laptop as the M2 SSD on my new desktop PC decided to stop working the other day.  But I thought I’d mention a couple of utilities that I’ve recently started using.

My new PC, just three months old when working has a 1TB M2 SSD with Windows on it. Most software is installed here. All the data, backups, everything else is stored on a 10 TB Hard disk. This is my 10th PC since 1989 so it has the name PC10. Yes, original I know.

I have been copying everything I’ve created and written since 1989 and like a snowball rolling down a hill it has grown. When I finished copying everything from my old PC; a process that took a large chunk of four days, I’d used 2.3 TB out of the 10 TB hard disk.   I just copied across the Gigabit network connection and it maxxed out at 113 MB/S. That’s even with anti-virus running. Of course Windows has an overhead so sometimes the transfer speed drops down to KB/S for small files. I worked it out that over the 48 hours (4 days- 12 hours a day), it copied at 13 MB/S average.

In future it might make sense to zip up folders with small files in them. In the meantime I need to do a bit of pruning of files, removing duplicates etc.

Everything

I’d been looking for a utility to let me find files quickly and somebody had suggested Everything. It’s brilliant. It tells me that I have just over 4 million files. I can filter on document types, images, music files or just search on matching names. And it is very very fast. If you want to find the massive file that’s eating up disk space or duplicates, it does it. But it’s only for Windows. Lacking a Windows system at the mo, I’ve just borrowed the image from the Everything home page.

Fsearch

FSearch window

Developer Christian Boxdörfer also liked Everything and decided to create a Unix clone of it which is FSearch. And it’s written in C. That’s it on the left.

I set it to find all C files and sorted by size.

 

Why I hate Assembly language…

Why I hate Assembly language…

6502 assembler listingI spent several years in the 1980s programming games.

I have a memory of 26 year old me sat hunched over a computer late at night back in 1985. I was working a 60-70 hour week as a partner in a games company. My current game was an American Civil War tactical wargame called Johnny Reb II. I was struggling with some ‘artificial intelligence’ code for the attackers (Confederate troops) to cross a bridge over a river. On the other side the defenders (Union) were trying to defend the bridge.

Johnny Reb II

Artificial Intelligence in games is a completely different thing from ML and Data Science nowadays. Back then it was just a control algorithm for troops reacting to the presence of enemy troops and working out the best routes, targets to attack, whether to retreat and so on.

What made it worse was that the whole thing was written in 6502 assembly language (and later converted to Z80). Back then you had two choices: Basic which was to be honest slow and clunky for writing games or assembly language. If I was doing it now, without a moments hesitation I’d program it in C. But C compilers for 6502 didn’t exist back then.

The Problem with assembly language

The problem with assembly language is (a) it’s slow to write. You can write 10 lines of C in the same time as ten lines of assembly code. Those ten lines of C will do far more than ten lines of assembly code. In 6502 all you are doing is moving values between registers or register <> memory. Maybe add a number or increment one of the three available registers A, X or Y. These were all 8-bit registers so you couldn’t even index easily through 64-bit memory. To do 16-bit indexing you stored the 16-bit address in two successive page-0 locations (addresses 0-255) and then used Y as an 8-bit index. You could do the same in page 0- memory with the X register.

(b). It takes a lot of code to do anything in assembly language. You want floating point arithmetic in 6502? Take a look.  I think Steve Wozniak wrote those for the Apple I/II. What we take for granted in languages like C# or Java or JavaScript is code for high level data structures like dictionaries. I’m sure it could be done but it takes a fair bit of programming. You don’t have those in assembly language; all you have to use is simple and not very long arrays.

In C# I wrote a program to read a 46 MB text file and produce a sorted count of all words in the file.  It used a Dictionary, took me 30 minutes to write and it ran in 5 seconds.  It would take weeks to do the same in assembler. 

6502 Page 0 locations were valuable because they made your code both shorter and faster.

I wrote a cross-assembler for 6502 in Z80 as a way to learn Z80. Assemblers use labels (L20, L30, L31 etc. in the screenshot) and I needed a way to hold them efficiently in memory. I ended up with a 26 x 26 index table of 2 byte pointers. If you had a label ‘ROUTE’ then there would be a pointer to a chain at the location for [‘R’][‘O’]. Each entry in the chain was like this

  • 1 byte length of rest of label (i.e. 3 for ‘UTE’) – 0 marks the end of the chain.
  • 3 bytes to hold ‘UTE’.
  • 2 byte address value

No need to hold the whole word as you know the first two letters. It also makes comparing a label against one in the table was faster because it only needed to match against len(label)-2 characters.

So the next value in the chain would start after that or be a 0 for the end of the chain. Yes most of the index table might be empty (all 26x26x2= 1352 bytes) but every label in a chain used 2 bytes less than the full label text. So with more than 676 labels you saved memory. Searching for a label was just a matter of walking a chain. Labels were just addresses; so a location could hold a value like a count. You’d identify it with a label and use that label in 6502 instructions. No variables in assembler; it’s all addresses…

With 6502 you need to do two passes to generate code. If you have a label in the first page of memory (0-255) then instructions are only two bytes long and are faster to execute than the three byte instructions. So on the first pass you don’t know if a LDA label will be 2 or 3 bytes long. After the first pass through though you do know now, so on the 2nd pass it can output the correct size instructions.

Programming in assembler means you have to write a lot of code and in the early days before I had a development machine that meant I had to save the source code to tape and compile it using a cartridge assembler. The CBM-64 could take cartridges and one of them stored assembly language in RAM just like Basic. If the game did something wrong then the CBM-64 would reset and you’d lose your source and have to reload it from the slow tape. Let’s hope you didn’t forget to save changes before you ran it. I spent a few hours gnashing my teeth over a persistent crash. I was calling a CLR routine when it should have been CLS! d’oh…

Note, from memory it was the Mikro cartridge assembler. See screenshot below.

Miro assembler start up screen.
Mikro Assembler Startup From Github

Jump Tables

So a game back then might be 5,000 lines of code or longer. That’s quite a bit to hold in memory, given that you need space for the game machine code, sprites, graphics etc. as well. Plus it’s wasteful having to recompile the same code over and over again. My cross-assembler did 250 lines per second but divide that by two for the two passes.

So I split up long files into smaller ones and created a jump table at the start. There was no linker so the code was loaded into RAM at fixed addresses. If you had five subroutines in one file then there’d be five jumps at the start to the actual function. And the files that called those functions just had a block of five calls at the start.

That way you didn’t have to worry exactly where the function was located in RAM so long as that file was always loaded at the same address.

 

Switching to Development Machines

It got easier when we switched to development machines. The CBM-64 had a parallel port as did the development machine (Tatung Einstein-a CP/M computer) so a little bit of handler code in the CBM-64 set up the CIA chip to wait for data sent down the parallel cable and put the code directly in RAM. It took no time to load the handler from tape after a crash and then send down the whole file.

Modern CPUs do all sort of optimizing tricks and that’s even before you use vectorization. Compiler writers know how to generate code that uses these tricks but it would take quite a while to learn them so you could use them in hand-written assembly.

Conclusion

Writing in assembler in the 80s was easy to learn. Nowadays I wouldn’t know where to start- the Intel and AMD CPUs have a lot of different chips in their families so there are variations in what instructions are available. Oh and don’t forget there’s ARM CPUs as well.

Writing in C (or even C++) is a lot easier to get into and I very much doubt if you’d get any better performance in writing things in assembly. Also, it would take a lot longer.