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; begin if AudioProcessor.Active then AudioProcessor.ProcessBlock(inputBuffer, framesPerBuffer); Move(inputBuffer^, outputBuffer^, framesPerBuffer * 2); // if PaInt16 MorseReceiver.ProcessBlock(inputBuffer, framesPerBuffer); Result := paContinue; end;
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; begin Active := true; fillchar(InputParams, SizeOf(InputParams), 0); with InputParams do begin ChannelCount := 1; Device := AudioIn; // Direct Sound from Receiver SampleFormat := paInt16; suggestedLatency := Pa_GetDeviceInfo(AudioIn).defaultLowInputLatency; end; fillchar(OutputParams, SizeOf(OutputParams), 0); with OutputParams do begin ChannelCount := 1; Device := AudioOut; // Direct Sound to PC Speaker SampleFormat := paInt16; suggestedLatency := Pa_GetDeviceInfo(AudioOut).defaultLowOutputLatency; end; CheckPA(Pa_OpenStream(Stream, @InputParams, @OutputParams, C_SAMPLERATE, 0, paNoFlag, @ExternalCallback, nil)); CheckPA(Pa_StartStream(Stream)); Report('External Stream Started'); end;
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); begin StopTimer.Enabled := false; CheckPA(Pa_StopStream(Stream)); sleep(500); Active := false; end;
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.