Hello,
I'm new at coding and I just started a new project at C, I'm trying to make an encoder and decoder for Morse code (with audio) that's means I can put text and encode it to audio beeps (morse - dot and dash) as you can see below:
Code:
#define _CRT_SECURE_NO_WARNINGS // To ingore VisualStudio C language errors
#include <windows.h> // To use output of the computer (speakers)
#include <utilapiset.h> // To use Beep function
#include <stdio.h> // To use standard input/output functions
#include <time.h> // To use time library of C
#include <stdlib.h> // To use more standard functions
#include "delay.h" // To call delay.h function
int main()
{
//----------------------------------Setting & Variables----------------------------------------//
system("cls");
char* alphamorse[] = {
".-",//a
"-...",//b
"-.-.",//c
"-..",//d
".",//e
"..-.",//f
"--.",//g
"....",//h
"..",//i
".---",//j
"-.-",//k
".-..",//l
"--",//m
"-.",//n
"---",//o
".--.",//p
"--.-",//q
".-.",//r
"...",//s
"-",//t
"..-",//u
"...-",//v
".--",//w
"-..-",//x
"-.--",//y
"--..",//z
};// All the alphabet in morse
char* nummorse[] = {
"-----",//0
".----",//1
"..---",//2
"...--",//3
"....-",//4
".....",//5
"-....",//6
"--...",//7
"---..",//8
"----."//9
}; // All the numbers in morse
char T[100]; // Transmit
//char R; // Receive
char enter[1]; // To recive enter input without interruption
int i = 0 ,j=0;
int count = 0;
unsigned int freq=550,dash=300,dot=100; // Recommended --> dash time x3 then dot
unsigned int delaydd = 0; // delay between dash/dots
unsigned int input = 0; //defult value of menu input
//---------------------------------------Menu UI-----------------------------------------------//
Menu:
input = 0; count = 0; i = 0, j = 0; // reset the Setting & Variables values
system("cls"); //clear screen
printf("\nDaniel Hoasov Cohen\n");
printf("\nUltrasonic Data Transmit & Receive - POC\n \nChoose one of the following options by entering the number:\n" "\n1.Transmit\n" "2.Receive\n" "3.Configuration\n" "4.Exit\n"); //UI main menu
do
{
printf("\nyour choose:");
scanf_s("%d", &input); // scan --> user input
} while (input > 4 || input < 0);
system("cls"); //clear screen
//---------------------------------------Main Menu---------------------------------------------//
switch (input)
{
case 1: goto Transmit; break; //if user input = 1 go to Transmit
//case 2: record(); break; //if user input = 2 go to Receive
case 3: goto Configuration; break; //if user input = 3 go to Configuration
case 4: exit(1); break; //if user input = 4 exit the software
}
return 0;
//----------------------------------Configuration Option---------------------------------------//
Configuration:
printf("\nCurrent configuration:"); // Configuration status
printf("\n Frequancy [Hz]: %d", freq);
printf("\n Dash time [msec]: %d", dash);
printf("\n Dot time [msec]: %d", dot);
printf("\n Delay between Dash/Dot [msec]: %d", delaydd);
printf("\n\nConfiguration edit:"); // Configuration status
printf("\n Enter Frequancy in the range 37 through 25000 [Hz]: \n"); // UI --> frequancy (Default --> unsigned int freq=550)
scanf_s("%d", &freq); // To recive input from user keyboard
gets(enter);//recive the 'Enter' pressing from user without interruption for the gets below
printf("\n Dash ('-') duration [msec]: \n"); // UI --> dash duration (Default 300msec)
scanf_s("%d", &dash); // To recive input from user keyboard
gets(enter);//recive the 'Enter' pressing from user without interruption for the gets below
printf("\n Dot ('.') duration [msec]: \n"); // UI --> dash duration (Default 100msec)
scanf_s("%d", &dot); // To recive input from user keyboard
gets(enter);//recive the 'Enter' pressing from user without interruption for the gets below
printf("\n Delay between Dash/Dot duration [msec]: \n"); // UI --> delay duration (Default 0msec)
scanf_s("%d", &delaydd); // To recive input from user keyboard
gets(enter);//recive the 'Enter' pressing from user without interruption for the gets below
goto Menu;
//------------------------------------Transmit Option------------------------------------------//
Transmit:
system("cls"); //clear screen
gets(enter);//recive the 'Enter' pressing from user without interruption for the gets below
printf("\nEnter a sentence:\n"); // UI --> string
gets(T); // To recive input from user keyboard
printf("\nYour input:\n"); // UI --> string show
puts(T); // To check user input
printf("\nMorse convert in progress...\n"); // UI
while (T[i] != '\0') // Convert the string to morse (the end of the string '\0')
{
if (T[i] != ' ' && (!isdigit(T[i]))) // if user input isnt space or number
{
printf("%s ", alphamorse[toupper(T[i]) - 65]); // Print the a-z string
printf("\nMorse sound in progress...\n");
for (j = 0; alphamorse[toupper(T[i]) - 65][j] != '\0'; j++) // Counting the numbers of dash/dots in the word
count++;
for (j = 0; j < count; j++)// j is the index of character
{
if (alphamorse[toupper(T[i]) - 65][j] == '.') // if index j is dot
{
delaymilisec(delaydd); // Delay between Dash/Dot
Beep(freq, dot); // More information below
}
else if (alphamorse[toupper(T[i]) - 65][j] == '-')// if index j is dash
{
delaymilisec(delaydd); // Delay between Dash/Dot
Beep(freq, dash); // More information below
}
}
}
if (T[i] == ' ') // if string with space print the space
{
printf(" ");
delaysec(1);// Delay to separate between spaces
}
if (isdigit(T[i]) && T[i] != ' ')// if user input is number but isnt space
{
printf("%s ", nummorse[T[i] - 48]);// print the 0-9 string
printf("\nMorse sound in progress...\n");
for (j = 0; nummorse[T[i] - 48][j] != '\0'; j++) // Counting the numbers of dash/dots in the word
count++;
for (j = 0; j < count; j++)// j is the index of character
{
if (nummorse[T[i] - 48][j] == '.') // if index j is dot
{
delaymilisec(delaydd); // Delay between Dash/Dot
Beep(freq, dot); // More information below
}
else if (nummorse[T[i] - 48][j] == '-')// if index j is dash
{
delaymilisec(delaydd); // Delay between Dash/Dot
Beep(freq, dash); // More information below
}
}
}
i++; // i is the index of the word
}
delaysec(1*count); // delay 2sec muliply counting the dash/dots
goto Menu;
}
the all idea is to generate morse code with specific configuration by the user (Frequency, time of dot, time of dash, time of interval between dot and dash)
but now I'm stuck at the decoder... I don't know what to do, I thought to open the microphone for live audio input and it will decode the morse code via the frequency of dot/dash and the time of them.
I started to do this code to use the microphone of the laptop (took it from AudioPort --> Paex record example)
Code:
/** @file paex_record.c
@ingroup examples_src
@brief Record input into an array; Save array to a file; Playback recorded data.
@author Phil Burk http://www.softsynth.com
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#define _CRT_SECURE_NO_WARNINGS // To ingore VisualStudio C language errors
#include <stdio.h>// To use standard input/output functions
#include <stdlib.h>// To use more standard functions
#include <portaudio.h>// To use an external lib and include --> microphone input
//-----------------------------------------Configuration-------------------------------------------------//
#define SAMPLE_RATE (44100) // #define SAMPLE_RATE (17932) --> Test failure to open with this value.
#define FRAMES_PER_BUFFER (512)
#define NUM_SECONDS (3)
#define NUM_CHANNELS (2)
// #define DITHER_FLAG (paDitherOff)
#define DITHER_FLAG (0) /**/
#define WRITE_TO_FILE (1) // Set to 1 if you want to capture the recording to a file.
//---------------------------------------Select sample format---------------------------------------------//
#if 1
#define PA_SAMPLE_TYPE paFloat32
typedef float SAMPLE;
#define SAMPLE_SILENCE (0.0f)
#define PRINTF_S_FORMAT "%.8f"
#elif 1
#define PA_SAMPLE_TYPE paInt16
typedef short SAMPLE;
#define SAMPLE_SILENCE (0)
#define PRINTF_S_FORMAT "%d"
#elif 0
#define PA_SAMPLE_TYPE paInt8
typedef char SAMPLE;
#define SAMPLE_SILENCE (0)
#define PRINTF_S_FORMAT "%d"
#else
#define PA_SAMPLE_TYPE paUInt8
typedef unsigned char SAMPLE;
#define SAMPLE_SILENCE (128)
#define PRINTF_S_FORMAT "%d"
#endif
typedef struct
{
int frameIndex; // Index into sample array.
int maxFrameIndex;
SAMPLE *recordedSamples;
}
paTestData;
/************************************************************************************
****This routine will be called by the PortAudio engine when audio is needed. ****
****It may be called at interrupt level on some machines so don't do anything ****
****that could mess up the system like calling malloc() or free(). ****
************************************************************************************/
static int recordCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
const SAMPLE *rptr = (const SAMPLE*)inputBuffer;
SAMPLE *wptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS];
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
(void) outputBuffer; // Prevent unused variable warnings.
(void) timeInfo;
(void) statusFlags;
(void) userData;
if( framesLeft < framesPerBuffer )
{
framesToCalc = framesLeft;
finished = paComplete;
}
else
{
framesToCalc = framesPerBuffer;
finished = paContinue;
}
if( inputBuffer == NULL )
{
for( i=0; i<framesToCalc; i++ )
{
*wptr++ = SAMPLE_SILENCE; // left
if( NUM_CHANNELS == 2 ) *wptr++ = SAMPLE_SILENCE; // right
}
}
else
{
for( i=0; i<framesToCalc; i++ )
{
*wptr++ = *rptr++; // left
if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++; // right
}
}
data->frameIndex += framesToCalc;
return finished;
}
/**********************************************************************************
****This routine will be called by the PortAudio engine when audio is needed. ****
****It may be called at interrupt level on some machines so don't do anything ****
****that could mess up the system like calling malloc() or free(). ****
**********************************************************************************/
static int playCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
SAMPLE *rptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS];
SAMPLE *wptr = (SAMPLE*)outputBuffer;
unsigned int i;
int finished;
unsigned int framesLeft = data->maxFrameIndex - data->frameIndex;
(void) inputBuffer; // Prevent unused variable warnings.
(void) timeInfo;
(void) statusFlags;
(void) userData;
if( framesLeft < framesPerBuffer )
{
for( i=0; i<framesLeft; i++ ) // final buffer...
{
*wptr++ = *rptr++; // left
if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++; // right
}
for( ; i<framesPerBuffer; i++ )
{
*wptr++ = 0; /* left */
if( NUM_CHANNELS == 2 ) *wptr++ = 0; // right
}
data->frameIndex += framesLeft;
finished = paComplete;
}
else
{
for( i=0; i<framesPerBuffer; i++ )
{
*wptr++ = *rptr++; // left
if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++; // right
}
data->frameIndex += framesPerBuffer;
finished = paContinue;
}
return finished;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters inputParameters,
outputParameters;
PaStream* stream;
PaError err = paNoError;
paTestData data;
int i;
int totalFrames;
int numSamples;
int numBytes;
SAMPLE max, val;
double average;
char input_user;
//---------------------------------------Waiting for input to start---------------------------------------------//
printf("\nPress any key to record\n");
input_user=getch();
//---------------------------------------------Prepare to record--------------------------------------------------//
printf("patest_record.c\n"); fflush(stdout);
data.maxFrameIndex = totalFrames = NUM_SECONDS * SAMPLE_RATE; // Record for a few seconds.
data.frameIndex = 0;
numSamples = totalFrames * NUM_CHANNELS;
numBytes = numSamples * sizeof(SAMPLE);
data.recordedSamples = (SAMPLE *) malloc( numBytes ); // From now on, recordedSamples is initialised.
if( data.recordedSamples == NULL )
{
printf("Could not allocate record array.\n");
goto done;
}
for( i=0; i<numSamples; i++ ) data.recordedSamples[i] = 0;
err = Pa_Initialize();
if( err != paNoError ) goto done;
inputParameters.device = Pa_GetDefaultInputDevice(); // default input device
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto done;
}
inputParameters.channelCount = 2; // stereo input
inputParameters.sampleFormat = PA_SAMPLE_TYPE;
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
//---------------------------------------------Start to record--------------------------------------------------//
err = Pa_OpenStream(
&stream,
&inputParameters,
NULL, /* &outputParameters, */
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
recordCallback,
&data );
if( err != paNoError ) goto done;
err = Pa_StartStream( stream );
if( err != paNoError ) goto done;
printf("\n=== Now recording. ===\n"); fflush(stdout);
while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
{
Pa_Sleep(1000);
printf("index = %d\n", data.frameIndex ); fflush(stdout);
}
if( err < 0 ) goto done;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto done;
// Measure maximum peak amplitude.
max = 0;
average = 0.0;
for( i=0; i<numSamples; i++ )
{
val = data.recordedSamples[i];
if( val < 0 ) val = -val; // ABS
if( val > max )
{
max = val;
}
average += val;
}
average = average / (double)numSamples;
printf("sample max amplitude = "PRINTF_S_FORMAT"\n", max );
printf("sample average = %lf\n", average );
printf("\nPress any key to listen the playback\n");
input_user = getch();
#if WRITE_TO_FILE // Write recorded data to a file.
{
FILE *fid;
fid = fopen("recorded.raw", "wb");
if( fid == NULL )
{
printf("Could not open file.");
}
else
{
fwrite( data.recordedSamples, NUM_CHANNELS * sizeof(SAMPLE), totalFrames, fid );
fclose( fid );
printf("Wrote data to 'recorded.raw'\n");
}
}
#endif
//---------------------------------------------Playback the record--------------------------------------------------//
data.frameIndex = 0;
outputParameters.device = Pa_GetDefaultOutputDevice(); // default output device
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto done;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
printf("\n=== Now playing back the record. ===\n"); fflush(stdout);
err = Pa_OpenStream(
&stream,
NULL, // no input
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
playCallback,
&data );
if( err != paNoError ) goto done;
if( stream )
{
err = Pa_StartStream( stream );
if( err != paNoError ) goto done;
printf("Waiting for playback to finish.\n"); fflush(stdout);
while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(100);
if( err < 0 ) goto done;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto done;
printf("Done.\n"); fflush(stdout);
}
done:
Pa_Terminate();
if( data.recordedSamples ) // Sure it is NULL or valid.
free( data.recordedSamples );
if( err != paNoError )
{
fprintf( stderr, "An error occured while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
err = 1; // Always return 0 or 1, but no other return codes.
}
printf("\nPress any key to exit\n");
input_user = getch();
return err;
}
how can I continue? I don't know what to do now.
I really need your help.