PDA

View Full Version : trying to call function from main.cpp to wave.cpp



duma
5th August 2011, 20:19
Hi guys,
I have created a program with QMainWindow on Qt Creator called wave and I have a function called generate_sine() in my main.cpp which I wish to call in my wave.cpp under my pushButton function. How do I do this?
What I tried was: I defined the function in main.cpp, I declared it in the header file(wave.h), and I tried to call/implement it in my wave file(wave.cpp) under the function: on_pushButton_clicked(). This is the way to do it in c++ programming, but its not working. Any help would be greatly appreciated.
Code is below for viewing:

main.cpp:
defining function:
...(some code)...

static int generate_sine(const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
int count, double *_phase)
{
static double max_phase = 2. * M_PI;
double phase = *_phase;
double step = max_phase*freq/(double)rate;
unsigned char *samples[channels];
int steps[channels];
unsigned int chn;
int format_bits = snd_pcm_format_width(format);
unsigned int maxval = (1 << (format_bits - 1)) - 1;
int bps = format_bits / 8; // bytes per sample
int phys_bps = snd_pcm_format_physical_width(format) / 8;
int big_endian = snd_pcm_format_big_endian(format) == 1;
int to_unsigned = snd_pcm_format_unsigned(format) == 1;
int is_float = (format == SND_PCM_FORMAT_FLOAT_LE ||
format == SND_PCM_FORMAT_FLOAT_BE);
float amplitude_scale = amplitude/8.56;


// verify and prepare the contents of areas
for (chn = 0; chn < channels; chn++) {
if ((areas[chn].first % 8) != 0) {
printf("areas[%i].first == %i, aborting...\n", chn, areas[chn].first);
exit(EXIT_FAILURE);
}
samples[chn] = (((unsigned char *)areas[chn].addr) + (areas[chn].first / 8));
if ((areas[chn].step % 16) != 0) {
printf("areas[%i].step == %i, aborting...\n", chn, areas[chn].step);
exit(EXIT_FAILURE);
}
steps[chn] = areas[chn].step / 8;
samples[chn] += offset * steps[chn];
}
// fill the channel areas
while (count-- > 0) {
union {
float f;
int i;
} fval;
int res, i;
if (is_float) {
fval.f = amplitude_scale * sin(phase) * maxval;
res = fval.i;
} else
res = amplitude_scale * sin(phase) * maxval;
if (to_unsigned)
res ^= 1U << (format_bits - 1);
for (chn = 0; chn < channels; chn++) {
// Generate data in native endian format
if (big_endian) {
for (i = 0; i < bps; i++)
*(samples[chn] + phys_bps - 1 - i) = (res >> i * 8) & 0xff;
} else {
for (i = 0; i < bps; i++)
*(samples[chn] + i) = (res >> i * 8) & 0xff;
}
samples[chn] += steps[chn];
}
phase += step;
if (phase >= max_phase)
phase -= max_phase;
}
*_phase = phase;
}......some code...

wave.cpp:


...(some code)...
void wave::on_pushButton_clicked()
{
freq = ui->frequency->text().toDouble();
ampl = ui->amplitude->text().toDouble();
snd_pcm_t *handle;
signed short *samples;
snd_pcm_channel_area_t *areas;
double phase = 0;
signed short *ptr;
int err, cptr;

while (isTrue) {
generate_sine(areas, 0, period_size, &phase); ..................calling function

ptr = samples;
cptr = period_size;
while (cptr > 0) {
err = snd_pcm_writei(handle, ptr, cptr);
if (err == -EAGAIN)
continue;
if (err < 0) {
if (xrun_recovery(handle, err) < 0) {
printf("Write error: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}
break; /* skip one period */
}
ptr += err * channels;
cptr -= err;
}
}...(some code)...

wave.h:
declaring function:

....(some code)...
class wave : public QMainWindow
{
Q_OBJECT

public:
explicit wave(QWidget *parent = 0);
~wave();

private slots:
void on_pushButton_clicked();

void on_pushButton_2_clicked();
private:
Ui::wave *ui;
static int generate_sine(const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
int count, double *_phase) ;

};

stampede
5th August 2011, 20:38
declare the function in header "generate_sine.h":


// generate_sine.h

#include something

extern void generate_sine( const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
int count, double *_phase );

and put the implementation in "generate_sine.cpp" (without the "static" keyword).
Add the sources to .pro file.
Then include "generate_sine.h" in "main.cpp" or wherever else you want to use the method.

duma
5th August 2011, 22:19
declare the function in header "generate_sine.h":


// generate_sine.h

#include something

extern void generate_sine( const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
int count, double *_phase );

and put the implementation in "generate_sine.cpp" (without the "static" keyword).
Add the sources to .pro file.
Then include "generate_sine.h" in "main.cpp" or wherever else you want to use the method.

Hi,
I tried this, it didn't work. Still getting the same error:

undefined reference to `wave::generate_sine(_snd_pcm_channel_area const*, unsigned long, int, double*)

generate_sine.cpp:


#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <cstdlib>
#include <string.h>
#include <cstring>
#include <sched.h>
#include <errno.h>
#include <getopt.h>
#include <alsa/asoundlib.h>
#include <sys/time.h>
#include <math.h>
#include <cmath>
#include <iostream>
using namespace std;

static const char *device = "plughw:0,0"; // playback device
static snd_pcm_format_t format = SND_PCM_FORMAT_S16; // sample format- change to 24-bit
static unsigned int rate = 96000; // stream rate
static unsigned int channels = 128; // count of channels
static unsigned int buffer_time = 500000; // ring buffer length in us
static unsigned int period_time = 100000; // period time in us
static double freq; // sinusoidal wave frequency in Hz
static int verbose = 0; // verbose flag
static int resample = 1; // enable alsa-lib resampling
static int period_event = 0; // produce poll event after each period
static snd_pcm_sframes_t buffer_size;
static snd_pcm_sframes_t period_size;
static snd_output_t *output = NULL;
static double ampl;
static snd_pcm_t *h;
static double amplitude;


int generate_sine(const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
int count, double *_phase)

{

static double max_phase = 2. * M_PI;
double phase = *_phase;
double step = max_phase*freq/(double)rate;
unsigned char *samples[channels];
int steps[channels];
unsigned int chn;
int format_bits = snd_pcm_format_width(format);
unsigned int maxval = (1 << (format_bits - 1)) - 1;
int bps = format_bits / 8; /* bytes per sample */
int phys_bps = snd_pcm_format_physical_width(format) / 8;
int big_endian = snd_pcm_format_big_endian(format) == 1;
int to_unsigned = snd_pcm_format_unsigned(format) == 1;
int is_float = (format == SND_PCM_FORMAT_FLOAT_LE ||
format == SND_PCM_FORMAT_FLOAT_BE);

float amplitude_scale = amplitude/8.56;

/* verify and prepare the contents of areas */
for (chn = 0; chn < channels; chn++) {
if ((areas[chn].first % 8) != 0) {
printf("areas[%i].first == %i, aborting...\n", chn, areas[chn].first);
exit(EXIT_FAILURE);
}
samples[chn] = /*(signed short *)*/(((unsigned char *)areas[chn].addr) + (areas[chn].first / 8));
if ((areas[chn].step % 16) != 0) {
printf("areas[%i].step == %i, aborting...\n", chn, areas[chn].step);
exit(EXIT_FAILURE);
}
steps[chn] = areas[chn].step / 8;
samples[chn] += offset * steps[chn];
}
/* fill the channel areas */
while (count-- > 0) {
union {
float f;
int i;
} fval;
int res, i;
if (is_float) {
fval.f = amplitude_scale * sin(phase) * maxval;
res = fval.i;
} else
res = amplitude_scale * sin(phase) * maxval;
if (to_unsigned)
res ^= 1U << (format_bits - 1);
for (chn = 0; chn < channels; chn++) {
/* Generate data in native endian format */
if (big_endian) {
for (i = 0; i < bps; i++)
*(samples[chn] + phys_bps - 1 - i) = (res >> i * 8) & 0xff;
} else {
for (i = 0; i < bps; i++)
*(samples[chn] + i) = (res >> i * 8) & 0xff;
}
samples[chn] += steps[chn];
}
phase += step;
if (phase >= max_phase)
phase -= max_phase;
}
*_phase = phase;
}

generate_sine.h:

#ifndef GENERATE_SINE_H
#define GENERATE_SINE_H
#include <alsa/asoundlib.h>
#include <QMainWindow>
#include <QObject>

extern void generate_sine(const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
int count, double *_phase );

#endif // GENERATE_SINE_H


wave.pro:

QT += core gui

TARGET = Wave
TEMPLATE = app


SOURCES += main.cpp\
wave.cpp \
generate_sine.cpp

HEADERS += wave.h \
generate_sine.h


LIBS += -lasound


FORMS += wave.ui

Added after 20 minutes:


declare the function in header "generate_sine.h":


// generate_sine.h

#include something

extern void generate_sine( const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
int count, double *_phase );

and put the implementation in "generate_sine.cpp" (without the "static" keyword).
Add the sources to .pro file.
Then include "generate_sine.h" in "main.cpp" or wherever else you want to use the method.

Hey thanks for the reply. This does allow me to call it in other files, but it doesn't let me call it under the on_pushButton_clicked() function. It gives me the error:

undefined reference to `wave::generate_sine(_snd_pcm_channel_area const*, unsigned long, int, double*)

stampede
5th August 2011, 22:39
undefined reference to `wave::generate_sine
Have you declared this method elsewhere ? For example, in wave namespace (or class) ? Can you show how you want to use it ?