Refactoring (2)

IC-7410 Rig Control Program (C++ version)_027

Added fft windows. (No waterfall windows yet.)

It seems that the code looks much better now, I mean more C++ like.

//============================================================================
// Name        : Rig008.cpp
//============================================================================

#include "SoundIC7410.h"
#include "SoundSoft66.h"
#include "MyDrawingArea.h"
#include <gtkmm.h>
#include <vector>
#include <iostream>
using namespace std;

int main(int argc, char *argv[]) {
	if (argc != 3) {
		cout << "Usage example: " << argv[0] << " hw:2,0 hw:1,0 " << endl;
		return 1;
	}

	vector <Sound*> soundlist;
	soundlist.push_back( new SoundIC7410{argv[1]} );
	soundlist.push_back( new SoundSoft66{argv[2]} );

	argc = 1;			/* just for the next line */
	Glib::RefPtr < Gtk::Application > app = Gtk::Application::create(argc, argv, "org.gtkmm.example");

	Gtk::Window   mywindow;
	Gtk::VBox     mybox;
	mywindow.set_title("IC-7410 Rig Control Program (C++ version)");

	for(auto s : soundlist) {
		mybox.pack_start( *(new MyDrawingArea{s}), FALSE, FALSE, 0 );
	}

	mywindow.add(mybox);
	mywindow.show_all();

	return app->run(mywindow);
}

We have two different types of sound devices (see lines 20-21), IC7410 (I channel only) and Soft66 (I and Q channels).

But in the for loop (see lines 30-32), we just use a pointer s to the base class Sound, which is an abstract class with pure virtual functions.

/* Sound.h */

#ifndef SOUND_H_
#define SOUND_H_

#include "AlsaParams.h"
#include <asoundlib.h>

class Sound : public AlsaParams {
public:
	Sound();
	virtual int get_channels() const = 0;
	virtual int asound_fftcopy() = 0;
	virtual ~Sound();
};

#endif /* SOUND_H_ */

The functions in the two derived classes, SoundIC7410 and SoundSoft66, override these virtual functions so that the different characteristics of the devices are treated properly.

/* SoundIC7410.h */

#ifndef SOUNDIC7410_H_
#define SOUNDIC7410_H_

#include "AlsaParams.h"
#include "Sound.h"

class SoundIC7410: public Sound {
public:
	SoundIC7410();
	SoundIC7410(char *s);
	int get_channels() const override { return 1; }
	int asound_fftcopy() override;
	virtual ~SoundIC7410();
};

#endif /* SOUNDIC7410_H_ */
/* SoundIC7410.cpp */

#include "SoundIC7410.h"
#include <iostream>
using namespace std;

SoundIC7410::SoundIC7410() {
}

SoundIC7410::SoundIC7410(char* s) {
	sound_device = s;
	channels = 1;
	rate = 32000;
	buffer_size = 32 * 1024;
	period_size =  8 * 1024;
	nfft = 4 * 1024; /* IC-7410 */
	samples            = new signed short[period_size * channels * 2];
	audio_signal       = new double      [period_size * channels * 2];
	audio_signal_ffted = new double [nfft];
	in_real = new double[nfft];
	out  = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * ( nfft/2 + 1 )*2 );
	plan = fftw_plan_dft_r2c_1d(nfft, in_real, out, FFTW_MEASURE);
	asound_init();
	asound_go();
}

int SoundIC7410::asound_fftcopy() {
	for (int i = 0; i < nfft; i++) {
		in_real[i] = audio_signal[i];
	}
	return 0;
}

SoundIC7410::~SoundIC7410() {
}

The important part is that there are no if nor switch statements to take care of the different types of devices.