Home » Blog » Christmas » PortAudio Reads Morse Code

PortAudio Reads Morse Code

portaudio reads morse

So, how do I get a Morse code signal into my decoding program? PortAudio reads Morse code audio just fine.

I have spent years playing around with audio components to get sampled audio into a Delphi program. Recently, I have settled on PortAudio to do the job.

PortAudio is a free,  cross-platform, open-source, audio I/O library. Installed as a dynamic link library, I can use PortAudio to access any of the native audio API on Microsoft Windows. As long as your receiver can output audio as either a PC audio input or through a virtual audio cable, you can get audio into your program.

Below, you can see a callback function which accepts an audio stream and moves it into your program in real time. In my case, I am using Direct Sound with a VAC.

function ExternalCallback(const inputBuffer: Pointer; outputBuffer: Pointer;
framesPerBuffer: Cardinal; const timeInfo: PPaStreamCallbackTimeInfo;
statusFlags: TPaStreamCallbackFlags; userData: Pointer): Integer; cdecl;
  if AudioProcessor.Active then
    AudioProcessor.ProcessBlock(inputBuffer, framesPerBuffer);
  Move(inputBuffer^, outputBuffer^, framesPerBuffer * 2); // if PaInt16
  MorseReceiver.ProcessBlock(inputBuffer, framesPerBuffer);
  Result := paContinue;

PortAudio reads Morse in buffers which you can then easily process. In my case, I am using 8000 samples per second of 16 bit audio.

procedure TfrmMain.StartAudio;
Active := true;
fillchar(InputParams, SizeOf(InputParams), 0);
with InputParams do
ChannelCount := 1;
Device := AudioIn; // Direct Sound from Receiver
SampleFormat := paInt16;
suggestedLatency := Pa_GetDeviceInfo(AudioIn).defaultLowInputLatency;
fillchar(OutputParams, SizeOf(OutputParams), 0);
with OutputParams do
ChannelCount := 1;
Device := AudioOut; // Direct Sound to PC Speaker
SampleFormat := paInt16;
suggestedLatency := Pa_GetDeviceInfo(AudioOut).defaultLowOutputLatency;
CheckPA(Pa_OpenStream(Stream, @InputParams, @OutputParams, C_SAMPLERATE, 0,
paNoFlag, @ExternalCallback, nil));
Report('External Stream Started');

PortAudio Reads Morse Code Audio

When the audio arrives, I can apply several filters to reduce bandwidth and noise. Then, the sounds are transferred to the Morse Receiver section where the decoding is managed.

I use a timer to stop the audio stream, which gives the Direct Sound buffers time to empty, as they are being provided by Windows.

procedure TfrmMain.StopAudio(Sender: TObject);
StopTimer.Enabled := false;

Active := false;

If you are writing software to process an audio stream, I recommend that you give PortAudio a try. It is stable and simple to use.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.