I'm trying to create a simple test to time some functions. I'm using the following files main.cpp and testTiming.hpp. I am not able to compile, I get the following error: main.cpp:16: undefined reference to `startProfile(TIME_ID)'. Is there anything incorrect about my function definitions?
testTiming.hpp
#include <iostream>
#include <fstream>
#include <time.h>
#include <stdlib.h>
enum TIME_ID
{
TIME1 = 0,
TIME2 = 1,
NUM_TIMES = 2
};
typedef struct timeTable
{
timespec lastStartTime;
timespec totalTime;
} timeTable;
timeTable mTimeTable[NUM_TIMES];
void inline stopProfile( TIME_ID timeId );
timespec inline diff(timespec start, timespec end)
{
timespec temp;
if ((end.tv_nsec-start.tv_nsec) < 0) {
temp.tv_sec = end.tv_sec - start.tv_sec - 1;
temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
} else {
temp.tv_sec = end.tv_sec - start.tv_sec;
temp.tv_nsec = end.tv_nsec - start.tv_nsec;
}
return temp;
}
void inline startprofile( TIME_ID timeId)
{
if (timeId = TIME1)
{
stopProfile(TIME1);
}
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(mTimeTable[timeId].lastStartTime));
//clock_gettime(CLOCK_REALTIME, &(mTimeTable[timeId].lastStartTime));
};
void inline stopProfile( TIME_ID timeId)
{
timespec stopTime;
timespec diffTime;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(stopTime));
//clock_gettime(CLOCK_REALTIME, &(stopTime));
diffTime = diff(mTimeTable[timeId].lastStartTime, stopTime);
mTimeTable[timeId].totalTime.tv_sec += diffTime.tv_sec;
mTimeTable[timeId].totalTime.tv_nsec += diffTime.tv_nsec;
if (timeId != TIME1)
{
startprofile(TIME1);
}
};
void printprofile(void)
{
int i;
for(i = 0; i < NUM_TIMES; i++)
{
switch( i)
{
case TIME1:
printf("PROFILE : TIME1: %f s\n", (float) mTimeTable[i].totalTime.tv_sec + float
(mTimeTable[i].totalTime.tv_nsec / 1000000000.0f) );
break;
case TIME2:
printf("PR0FILE : TIME2P: %d %f s\n", (float) mTimeTable[i].totalTime.tv_sec + float
(mTimeTable[i].totalTime.tv_nsec / 1000000000.0f) );
printf("PR0FILE : TIME2W: %d %f s\n", (float) mTimeTable[i].totalTime.tv_sec + float
(mTimeTable[i].totalTime.tv_nsec) );
break;
default:
break;
}
}
};
main.cpp
#include "testTiming.hpp"
#include <time.h>
using namespace std;
void inline startProfile( TIME_ID timeId );
void inline printProfile( void );
int main(int argc, char** argv)
{
int sec = 5;
startProfile(TIME1);
sleep(sec);
stopProfile(TIME1);
//printProfile();
return 0;
}
Makefile
ls SHELL = /bin/csh
all :
g++ main.cpp -g -o timeTest
clean:
rm -f timeTest
Related
I need to execute multiple methods with specified interval(1 millisecond). Is there any way to call the methods in a loop without sleep because I am not getting 1000 entries in a log file for a second
Currently I have implemented using sleep. Data collection also might take little time.
#include <iostream>
#include <string>
#include <unordered_map>
#include <functional>
#include <csignal>
#include <chrono>
#include <thread>
#include <fstream>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <windows.h>
#include <atomic>
volatile std::sig_atomic_t gStatus{};
void signalHandler(int sig) {
gStatus = sig;
}
void feature1(std::string &output) { output = "feature1"; }
void feature2(std::string &output) { output = "feature2"; }
void feature3(std::string &output) { output = "feature3"; }
void feature4(std::string &output) { output = "feature4"; }
void feature5(std::string &output) { output = "feature5"; }
void feature6(std::string &output) { output = "feature6"; }
void processInfoRequest(std::string logFile, std::unordered_map<std::string, std::function<void(std::string &value)>> methodMap)
{
std::ofstream ofs(logFile);
std::uint64_t prevTime = 0, curTime = 0, diffTime = 0, tmpTime = 0, scheduleTime = 0, pollPeriod = 1;
prevTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
while (gStatus != SIGINT)
{
prevTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
prevTime = prevTime - scheduleTime;
**//get value**
auto timenow = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
ofs << ctime(&timenow);
for(auto it : methodMap)
{
std::string output;
it.second(output);
ofs << output << ",";
}
ofs << "\n";
curTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
diffTime = curTime - prevTime;
if (diffTime < pollPeriod)
{
diffTime = pollPeriod - diffTime;
curTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
std::uint64_t i = 0;
std::uint64_t n = diffTime / 10;
std::uint64_t remainingMs = diffTime % 10;
for (i = 0; i < n; i++)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
std::this_thread::sleep_for(std::chrono::milliseconds(remainingMs));
tmpTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
scheduleTime = tmpTime - (curTime + diffTime);
}
else
{
scheduleTime = 0;
}
}
ofs.close();
}
int main()
{
std::signal(SIGINT, signalHandler);
std::string output;
std::unordered_map<std::string, std::function<void(std::string &value)>> methodMap = {
{"f1", feature1},
{"f2", feature2},
{"f3", feature3},
{"f4", feature4},
{"f5", feature5},
{"f6", feature6}
};
std::thread th1 = std::thread(processInfoRequest, "threadlog.csv", methodMap);
if (th1.joinable())
th1.join();
return 0;
}
When I call QueryPerformanceCounter many times in a shot time, it gives me a wrong output. The code is working an amount of loop iteration, and at a point the QueryPerformanceCounter returns 2 consecutive different values.
Code:
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <math.h>
//timer (us)
double PCFreq = 0.0;
__int64 CounterStart = 0;
//prototypage
double micros(void);
void StartCounter(void);
int main()
{
StartCounter();
//initialisation time
printf("go\n");
for (long i = 0; i < 100000000; i += 1) {
double time_stamp1 = micros();
double time_stamp2 = micros();
if (fabs(time_stamp1 - time_stamp2) > 1000) {
printf("time_stamp1 : %lf\n", time_stamp1);
printf("time_stamp2 : %lf\n", time_stamp2);
printf("i : %ld\n", i);
break;
}
}
printf("finish\n");
}
void StartCounter() {
LARGE_INTEGER li;
if (!QueryPerformanceFrequency(&li)) {
printf("not initialized");
}
PCFreq = double(li.QuadPart) / 1000000.0;
QueryPerformanceCounter(&li);
CounterStart = li.QuadPart;
}
double micros() {
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return double(li.QuadPart - CounterStart) / PCFreq;
}
Unexpected output:
go
time_stamp1 : 709840.300000
time_stamp2 : 712229.000000
i : 5524494
finish
I am putting both the CPP and HPP files here and the error I receive:
I am adding the complete code here and the error I am encountering; kindly help.
Kindly help me in posting this question too.
CPP:
#include "TimeWindowCounter.hpp"
#include <iostream>
#include "../../Common/TimeAnalyser.hpp"
TimeWindowCounter::TimeWindowCounter()
{
init();
}
void TimeWindowCounter::init()
{
boost::atomic<bool> first_order_sent(false);
}
TimeWindowCounter::TimeWindowCounter(double currTime)
{
first_order_sent = true;
startTime = currTime;
endTime = currTime;
orderCount = 0;
ind = 0;
N = 1000;
for (int j =0; j<= 99; j++ )
numberofOrder[j] = 0;
}
TimeWindowCounter::~TimeWindowCounter()
{
}
void TimeWindowCounter::addOrder()
{
orderCount++;
numberofOrder[ind] = orderCount;
}
void TimeWindowCounter::clockTick(const boost::system::error_code& /*e*/, boost::asio::deadline_timer* t, int* count, double* currTime)
{
stopTime = *currTime;
WindowSize = timeAnalyser.getDiffTime_rt(startTime, stopTime);
if (WindowSize.count()*1000 > N)
startTime = startTime + (WindowSize.count()*1000-N);
ind = (ind + 1) % 10;
std::cout << *count << std::endl;
++(*count);
t->expires_at(t->expires_at() + boost::posix_time::milliseconds(1));
t->async_wait(boost::bind(clockTick,boost::asio::placeholders::error, t, count, currTime));
} // 10ms or 100 times a second
int TimeWindowCounter::getNumOfOrders()
{
int sum = 0;
for (int i = 0; i<= 99; i++)
sum = sum + numberofOrder[i];
return sum;
}
void TimeWindowCounter::run(){
io.run();
}
int main()
{
boost::asio::io_service io;
int count = 0;
TimeAnalyser timeAnalyser;
double currTime = timeAnalyser.getClockTime();
TimeWindowCounter * timewindowCounter = new TimeWindowCounter();
boost::asio::deadline_timer t(io, boost::posix_time::milliseconds(10));
t.async_wait(boost::bind(clockTick,boost::asio::placeholders::error, &t, &count, &currTime));
timewindowCounter->run();
for (int j = 0; j <=100000 ; j++)
timewindowCounter->addOrder();
std::cout << "Final count is " << count << std::endl;
}
HPP:
#ifndef TIMEWINDOWCOUNTER
#define TIMEWINDOWCOUNTER
#include <iostream>
#include <boost/chrono.hpp>
#include <boost/atomic.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <cmath>
#include <unistd.h>
#include "../../Common/TimeAnalyser.hpp"
using namespace std;
class TimeWindowCounter
{
TimeAnalyser timeAnalyser;
boost::asio::io_service io;
public:
TimeWindowCounter();
~TimeWindowCounter();
TimeWindowCounter(double currTime);
boost::atomic<bool> first_order_sent;
boost::chrono::duration<double> interval;
double startTime;
double stopTime;
double endTime;
double currTime;
void init();
int numberofOrders;
int orderCount;
int numberofOrder[99];
int ind;
boost::chrono::duration<double> WindowSize;
int N; // WindowSize
void addOrder();
void clockTick(const boost::system::error_code&, boost::asio::deadline_timer* t, int* count, double* currTime); // 10ms or 100 times a second
int getNumOfOrders();
void timer_thread();
void run();
};
#endif
Compile:
g++ -std=c++11 -o TA TimeWindowCounter.cpp -lboost_chrono -lboost_system
Error:
TimeWindowCounter.cpp: In member function ‘void TimeWindowCounter::clockTick(const boost::system::error_code&, boost::asio::deadline_timer*, int*, double*)’:
TimeWindowCounter.cpp:50:93: error: invalid use of non-static member function
t->async_wait(boost::bind(clockTick,boost::asio::placeholders::error, t, count, currTime));
^
TimeWindowCounter.cpp: In function ‘int main()’:
TimeWindowCounter.cpp:80:26: error: ‘clockTick’ was not declared in this scope
t.async_wait(boost::bind(clockTick,boost::asio::placeholders::error, &t, &count, &currTime));
You're binding an instance member function.
You need to qualify the function name and pass a suitable "this" parameter as the first argument:
t->async_wait(boost::bind(&TimeWindowCounter::clockTick, this, boost::asio::placeholders::error, t, count, currTime));
and
t.async_wait(boost::bind(&TimeWindowCounter::clockTick, timewindowCounter, boost::asio::placeholders::error, &t, &count, &currTime));
respectively.
Live Demo
Live On Coliru
#ifndef TIMEWINDOWCOUNTER
#define TIMEWINDOWCOUNTER
#include <iostream>
#include <boost/chrono.hpp>
#include <boost/atomic.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <cmath>
#include <unistd.h>
//#include "../../Common/TimeAnalyser.hpp"
struct TimeAnalyser {
double getClockTime() const { return 0; }
boost::chrono::duration<double> getDiffTime_rt(double, double) const { return boost::chrono::milliseconds(1); }
};
using namespace std;
class TimeWindowCounter {
TimeAnalyser timeAnalyser;
boost::asio::io_service io;
public:
TimeWindowCounter();
~TimeWindowCounter();
TimeWindowCounter(double currTime);
boost::atomic<bool> first_order_sent;
boost::chrono::duration<double> interval;
double startTime;
double stopTime;
double endTime;
double currTime;
void init();
int numberofOrders;
int orderCount;
int numberofOrder[99];
int ind;
boost::chrono::duration<double> WindowSize;
int N; // WindowSize
void addOrder();
void clockTick(const boost::system::error_code&, boost::asio::deadline_timer* t, int* count,
double* currTime); // 10ms or 100 times a second
int getNumOfOrders();
void timer_thread();
void run();
};
#endif
//#include "TimeWindowCounter.hpp"
#include <iostream>
//#include "../../Common/TimeAnalyser.hpp"
TimeWindowCounter::TimeWindowCounter() { init(); }
void TimeWindowCounter::init() { boost::atomic<bool> first_order_sent(false); }
TimeWindowCounter::TimeWindowCounter(double currTime)
{
first_order_sent = true;
startTime = currTime;
endTime = currTime;
orderCount = 0;
ind = 0;
N = 1000;
for (int j = 0; j <= 99; j++)
numberofOrder[j] = 0;
}
TimeWindowCounter::~TimeWindowCounter() {}
void TimeWindowCounter::addOrder()
{
orderCount++;
numberofOrder[ind] = orderCount;
}
void TimeWindowCounter::clockTick(const boost::system::error_code& /*e*/, boost::asio::deadline_timer* t, int* count,
double* currTime)
{
stopTime = *currTime;
WindowSize = timeAnalyser.getDiffTime_rt(startTime, stopTime);
if (WindowSize.count() * 1000 > N)
startTime = startTime + (WindowSize.count() * 1000 - N);
ind = (ind + 1) % 10;
std::cout << *count << std::endl;
++(*count);
t->expires_at(t->expires_at() + boost::posix_time::milliseconds(1));
t->async_wait(boost::bind(&TimeWindowCounter::clockTick, this, boost::asio::placeholders::error, t, count, currTime));
} // 10ms or 100 times a second
int TimeWindowCounter::getNumOfOrders()
{
int sum = 0;
for (int i = 0; i <= 99; i++)
sum = sum + numberofOrder[i];
return sum;
}
void TimeWindowCounter::run() { io.run(); }
int main()
{
boost::asio::io_service io;
int count = 0;
TimeAnalyser timeAnalyser;
double currTime = timeAnalyser.getClockTime();
TimeWindowCounter* timewindowCounter = new TimeWindowCounter();
boost::asio::deadline_timer t(io, boost::posix_time::milliseconds(10));
t.async_wait(boost::bind(&TimeWindowCounter::clockTick, timewindowCounter, boost::asio::placeholders::error, &t, &count, &currTime));
timewindowCounter->run();
for (int j = 0; j <= 100000; j++)
timewindowCounter->addOrder();
std::cout << "Final count is " << count << std::endl;
}
Prints
Final count is 0
i am having problems understanding how the audio part of the sdl library works
now, i know that when you initialize it, you have to specify the frequency and a >>callback<< function, which i think is then called automatically at the given frequency.
can anyone who worked with the sdl library write a simple example that would use sdl_audio to generate a 440 hz square wave (since it is the simplest waveform) at a sampling frequency of 44000 hz?
The Introduction to SDL (2011 cached version: 2) has got a neat example of using SDL Sound library that should get you started: http://www.libsdl.org/intro.en/usingsound.html
EDIT: Here is a working program that does what you asked for. I modified a bit the code found here: http://www.dgames.org/beep-sound-with-sdl/
#include <SDL/SDL.h>
#include <SDL/SDL_audio.h>
#include <queue>
#include <cmath>
const int AMPLITUDE = 28000;
const int FREQUENCY = 44100;
struct BeepObject
{
double freq;
int samplesLeft;
};
class Beeper
{
private:
double v;
std::queue<BeepObject> beeps;
public:
Beeper();
~Beeper();
void beep(double freq, int duration);
void generateSamples(Sint16 *stream, int length);
void wait();
};
void audio_callback(void*, Uint8*, int);
Beeper::Beeper()
{
SDL_AudioSpec desiredSpec;
desiredSpec.freq = FREQUENCY;
desiredSpec.format = AUDIO_S16SYS;
desiredSpec.channels = 1;
desiredSpec.samples = 2048;
desiredSpec.callback = audio_callback;
desiredSpec.userdata = this;
SDL_AudioSpec obtainedSpec;
// you might want to look for errors here
SDL_OpenAudio(&desiredSpec, &obtainedSpec);
// start play audio
SDL_PauseAudio(0);
}
Beeper::~Beeper()
{
SDL_CloseAudio();
}
void Beeper::generateSamples(Sint16 *stream, int length)
{
int i = 0;
while (i < length) {
if (beeps.empty()) {
while (i < length) {
stream[i] = 0;
i++;
}
return;
}
BeepObject& bo = beeps.front();
int samplesToDo = std::min(i + bo.samplesLeft, length);
bo.samplesLeft -= samplesToDo - i;
while (i < samplesToDo) {
stream[i] = AMPLITUDE * std::sin(v * 2 * M_PI / FREQUENCY);
i++;
v += bo.freq;
}
if (bo.samplesLeft == 0) {
beeps.pop();
}
}
}
void Beeper::beep(double freq, int duration)
{
BeepObject bo;
bo.freq = freq;
bo.samplesLeft = duration * FREQUENCY / 1000;
SDL_LockAudio();
beeps.push(bo);
SDL_UnlockAudio();
}
void Beeper::wait()
{
int size;
do {
SDL_Delay(20);
SDL_LockAudio();
size = beeps.size();
SDL_UnlockAudio();
} while (size > 0);
}
void audio_callback(void *_beeper, Uint8 *_stream, int _length)
{
Sint16 *stream = (Sint16*) _stream;
int length = _length / 2;
Beeper* beeper = (Beeper*) _beeper;
beeper->generateSamples(stream, length);
}
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_AUDIO);
int duration = 1000;
double Hz = 440;
Beeper b;
b.beep(Hz, duration);
b.wait();
return 0;
}
Good luck.
A boiled-down variant of the beeper-example, reduced to the bare minimum (with error-handling).
#include <math.h>
#include <SDL.h>
#include <SDL_audio.h>
const int AMPLITUDE = 28000;
const int SAMPLE_RATE = 44100;
void audio_callback(void *user_data, Uint8 *raw_buffer, int bytes)
{
Sint16 *buffer = (Sint16*)raw_buffer;
int length = bytes / 2; // 2 bytes per sample for AUDIO_S16SYS
int &sample_nr(*(int*)user_data);
for(int i = 0; i < length; i++, sample_nr++)
{
double time = (double)sample_nr / (double)SAMPLE_RATE;
buffer[i] = (Sint16)(AMPLITUDE * sin(2.0f * M_PI * 441.0f * time)); // render 441 HZ sine wave
}
}
int main(int argc, char *argv[])
{
if(SDL_Init(SDL_INIT_AUDIO) != 0) SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
int sample_nr = 0;
SDL_AudioSpec want;
want.freq = SAMPLE_RATE; // number of samples per second
want.format = AUDIO_S16SYS; // sample type (here: signed short i.e. 16 bit)
want.channels = 1; // only one channel
want.samples = 2048; // buffer-size
want.callback = audio_callback; // function SDL calls periodically to refill the buffer
want.userdata = &sample_nr; // counter, keeping track of current sample number
SDL_AudioSpec have;
if(SDL_OpenAudio(&want, &have) != 0) SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "Failed to open audio: %s", SDL_GetError());
if(want.format != have.format) SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "Failed to get the desired AudioSpec");
SDL_PauseAudio(0); // start playing sound
SDL_Delay(1000); // wait while sound is playing
SDL_PauseAudio(1); // stop playing sound
SDL_CloseAudio();
return 0;
}
SDL 2 C example
The following code produces a sinusoidal sound, it is adapted from: https://codereview.stackexchange.com/questions/41086/play-some-sine-waves-with-sdl2
main.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <SDL2/SDL.h>
const double ChromaticRatio = 1.059463094359295264562;
const double Tao = 6.283185307179586476925;
Uint32 sampleRate = 48000;
Uint32 frameRate = 60;
Uint32 floatStreamLength = 1024;
Uint32 samplesPerFrame;
Uint32 msPerFrame;
double practicallySilent = 0.001;
Uint32 audioBufferLength = 48000;
float *audioBuffer;
SDL_atomic_t audioCallbackLeftOff;
Sint32 audioMainLeftOff;
Uint8 audioMainAccumulator;
SDL_AudioDeviceID AudioDevice;
SDL_AudioSpec audioSpec;
SDL_Event event;
SDL_bool running = SDL_TRUE;
typedef struct {
float *waveform;
Uint32 waveformLength;
double volume;
double pan;
double frequency;
double phase;
} voice;
void speak(voice *v) {
float sample;
Uint32 sourceIndex;
double phaseIncrement = v->frequency/sampleRate;
Uint32 i;
if (v->volume > practicallySilent) {
for (i = 0; (i + 1) < samplesPerFrame; i += 2) {
v->phase += phaseIncrement;
if (v->phase > 1)
v->phase -= 1;
sourceIndex = v->phase*v->waveformLength;
sample = v->waveform[sourceIndex]*v->volume;
audioBuffer[audioMainLeftOff+i] += sample*(1-v->pan);
audioBuffer[audioMainLeftOff+i+1] += sample*v->pan;
}
}
else {
for (i=0; i<samplesPerFrame; i+=1)
audioBuffer[audioMainLeftOff+i] = 0;
}
audioMainAccumulator++;
}
double getFrequency(double pitch) {
return pow(ChromaticRatio, pitch-57)*440;
}
int getWaveformLength(double pitch) {
return sampleRate / getFrequency(pitch)+0.5f;
}
void buildSineWave(float *data, Uint32 length) {
Uint32 i;
for (i=0; i < length; i++)
data[i] = sin(i*(Tao/length));
}
void logSpec(SDL_AudioSpec *as) {
printf(
" freq______%5d\n"
" format____%5d\n"
" channels__%5d\n"
" silence___%5d\n"
" samples___%5d\n"
" size______%5d\n\n",
(int) as->freq,
(int) as->format,
(int) as->channels,
(int) as->silence,
(int) as->samples,
(int) as->size
);
}
void logVoice(voice *v) {
printf(
" waveformLength__%d\n"
" volume__________%f\n"
" pan_____________%f\n"
" frequency_______%f\n"
" phase___________%f\n",
v->waveformLength,
v->volume,
v->pan,
v->frequency,
v->phase
);
}
void logWavedata(float *floatStream, Uint32 floatStreamLength, Uint32 increment) {
printf("\n\nwaveform data:\n\n");
Uint32 i=0;
for (i = 0; i < floatStreamLength; i += increment)
printf("%4d:%2.16f\n", i, floatStream[i]);
printf("\n\n");
}
void audioCallback(void *unused, Uint8 *byteStream, int byteStreamLength) {
float* floatStream = (float*) byteStream;
Sint32 localAudioCallbackLeftOff = SDL_AtomicGet(&audioCallbackLeftOff);
Uint32 i;
for (i = 0; i < floatStreamLength; i++) {
floatStream[i] = audioBuffer[localAudioCallbackLeftOff];
localAudioCallbackLeftOff++;
if (localAudioCallbackLeftOff == audioBufferLength)
localAudioCallbackLeftOff = 0;
}
SDL_AtomicSet(&audioCallbackLeftOff, localAudioCallbackLeftOff);
}
int init(void) {
SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER);
SDL_AudioSpec want;
SDL_zero(want);
want.freq = sampleRate;
want.format = AUDIO_F32;
want.channels = 2;
want.samples = floatStreamLength;
want.callback = audioCallback;
AudioDevice = SDL_OpenAudioDevice(NULL, 0, &want, &audioSpec, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
if (AudioDevice == 0) {
printf("\nFailed to open audio: %s\n", SDL_GetError());
return 1;
}
printf("want:\n");
logSpec(&want);
printf("audioSpec:\n");
logSpec(&audioSpec);
if (audioSpec.format != want.format) {
printf("\nCouldn't get Float32 audio format.\n");
return 2;
}
sampleRate = audioSpec.freq;
floatStreamLength = audioSpec.size / 4;
samplesPerFrame = sampleRate / frameRate;
msPerFrame = 1000 / frameRate;
audioMainLeftOff = samplesPerFrame * 8;
SDL_AtomicSet(&audioCallbackLeftOff, 0);
if (audioBufferLength % samplesPerFrame)
audioBufferLength += samplesPerFrame - (audioBufferLength % samplesPerFrame);
audioBuffer = malloc(sizeof(float) * audioBufferLength);
return 0;
}
int onExit(void) {
SDL_CloseAudioDevice(AudioDevice);
SDL_Quit();
return 0;
}
int main(int argc, char *argv[]) {
float syncCompensationFactor = 0.0016;
Sint32 mainAudioLead;
Uint32 i;
voice testVoiceA;
voice testVoiceB;
voice testVoiceC;
testVoiceA.volume = 1;
testVoiceB.volume = 1;
testVoiceC.volume = 1;
testVoiceA.pan = 0.5;
testVoiceB.pan = 0;
testVoiceC.pan = 1;
testVoiceA.phase = 0;
testVoiceB.phase = 0;
testVoiceC.phase = 0;
testVoiceA.frequency = getFrequency(45);
testVoiceB.frequency = getFrequency(49);
testVoiceC.frequency = getFrequency(52);
Uint16 C0waveformLength = getWaveformLength(0);
testVoiceA.waveformLength = C0waveformLength;
testVoiceB.waveformLength = C0waveformLength;
testVoiceC.waveformLength = C0waveformLength;
float sineWave[C0waveformLength];
buildSineWave(sineWave, C0waveformLength);
testVoiceA.waveform = sineWave;
testVoiceB.waveform = sineWave;
testVoiceC.waveform = sineWave;
if (init())
return 1;
SDL_Delay(42);
SDL_PauseAudioDevice(AudioDevice, 0);
while (running) {
while (SDL_PollEvent(&event) != 0) {
if (event.type == SDL_QUIT) {
running = SDL_FALSE;
}
}
for (i = 0; i < samplesPerFrame; i++)
audioBuffer[audioMainLeftOff+i] = 0;
speak(&testVoiceA);
speak(&testVoiceB);
speak(&testVoiceC);
if (audioMainAccumulator > 1) {
for (i=0; i<samplesPerFrame; i++) {
audioBuffer[audioMainLeftOff+i] /= audioMainAccumulator;
}
}
audioMainAccumulator = 0;
audioMainLeftOff += samplesPerFrame;
if (audioMainLeftOff == audioBufferLength)
audioMainLeftOff = 0;
mainAudioLead = audioMainLeftOff - SDL_AtomicGet(&audioCallbackLeftOff);
if (mainAudioLead < 0)
mainAudioLead += audioBufferLength;
if (mainAudioLead < floatStreamLength)
printf("An audio collision may have occured!\n");
SDL_Delay(mainAudioLead * syncCompensationFactor);
}
onExit();
return 0;
}
Compile and run:
gcc -ggdb3 -O3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c -lSDL2 -lm
./main.out
Should be easy to turn this into a simple piano with: https://github.com/cirosantilli/cpp-cheat/blob/f734a2e76fbcfc67f707ae06be7a2a2ef5db47d1/c/interactive/audio_gen.c#L44
For wav manipulation, also check the official examples:
http://hg.libsdl.org/SDL/file/e12c38730512/test/testresample.c
http://hg.libsdl.org/SDL/file/e12c38730512/test/loopwave.c
Tested on Ubuntu 19.10, SDL 2.0.10.
This is a minimal example of how to play a sine wave in SDL2.
Make sure to call SDL_Init(SDL_INIT_AUDIO) before creating an instance of Sound.
Sound.h
#include <cstdint>
#include <SDL2/SDL.h>
class Sound
{
public:
Sound();
~Sound();
void play();
void stop();
const double m_sineFreq;
const double m_sampleFreq;
const double m_samplesPerSine;
uint32_t m_samplePos;
private:
static void SDLAudioCallback(void *data, Uint8 *buffer, int length);
SDL_AudioDeviceID m_device;
};
Sound.cpp
#include "Sound.h"
#include <cmath>
#include <iostream>
Sound::Sound()
: m_sineFreq(1000),
m_sampleFreq(44100),
m_samplesPerSine(m_sampleFreq / m_sineFreq),
m_samplePos(0)
{
SDL_AudioSpec wantSpec, haveSpec;
SDL_zero(wantSpec);
wantSpec.freq = m_sampleFreq;
wantSpec.format = AUDIO_U8;
wantSpec.channels = 1;
wantSpec.samples = 2048;
wantSpec.callback = SDLAudioCallback;
wantSpec.userdata = this;
m_device = SDL_OpenAudioDevice(NULL, 0, &wantSpec, &haveSpec, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
if (m_device == 0)
{
std::cout << "Failed to open audio: " << SDL_GetError() << std::endl;
}
}
Sound::~Sound()
{
SDL_CloseAudioDevice(m_device);
}
void Sound::play()
{
SDL_PauseAudioDevice(m_device, 0);
}
void Sound::stop()
{
SDL_PauseAudioDevice(m_device, 1);
}
void Sound::SDLAudioCallback(void *data, Uint8 *buffer, int length)
{
Sound *sound = reinterpret_cast<Sound*>(data);
for(int i = 0; i < length; ++i)
{
buffer[i] = (std::sin(sound->m_samplePos / sound->m_samplesPerSine * M_PI * 2) + 1) * 127.5;
++sound->m_samplePos;
}
}
I have noted that the cascades trained with the program opencv_traincascade does not run with the current version of opencv_performance. I've tried to convert the old performance cpp file to load the new types of cascades, but without success. The code is here:
#include "cv.h"
#include "highgui.h"
#include <cstdio>
#include <cmath>
#include <ctime>
#include <math.h>
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#ifndef PATH_MAX
#define PATH_MAX 512
#endif /* PATH_MAX */
/*typedef struct HidCascade {
int size;
int count;
} HidCascade;
*/
typedef struct ObjectPos {
float x;
float y;
float width;
int found; /* for reference */
int neghbors;
} ObjectPos;
using namespace std;
using namespace cv;
int main(int argc, char* argv[]) {
int i, j;
char* classifierdir = NULL;
//char* samplesdir = NULL;
int saveDetected = 1;
double scale_factor = 1.1;
float maxSizeDiff = 1.5F;
float maxPosDiff = 1.1F;
/* number of stages. if <=0 all stages are used */
//int nos = -1, nos0;
int width = 25;
int height = 15;
int rocsize;
FILE* info;
FILE* resultados;
char* infoname;
char fullname[PATH_MAX];
//char detfilename[PATH_MAX];
char* filename;
//char detname[] = "det-";
CascadeClassifier cascade;
double totaltime;
if (!(resultados = fopen("resultados.txt", "w"))) {
printf("Cannot create results file.\n");
exit(-1);
}
infoname = (char*) "";
rocsize = 20;
if (argc == 1) {
printf("Usage: %s\n -data <classifier_directory_name>\n"
" -info <collection_file_name>\n"
" [-maxSizeDiff <max_size_difference = %f>]\n"
" [-maxPosDiff <max_position_difference = %f>]\n"
" [-sf <scale_factor = %f>]\n"
" [-ni]\n"
" [-rs <roc_size = %d>]\n"
" [-w <sample_width = %d>]\n"
" [-h <sample_height = %d>]\n", argv[0], maxSizeDiff,
maxPosDiff, scale_factor, rocsize, width, height);
return 0;
}
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-data")) {
classifierdir = argv[++i];
} else if (!strcmp(argv[i], "-info")) {
infoname = argv[++i];
} else if (!strcmp(argv[i], "-maxSizeDiff")) {
maxSizeDiff = (float) atof(argv[++i]);
} else if (!strcmp(argv[i], "-maxPosDiff")) {
maxPosDiff = (float) atof(argv[++i]);
} else if (!strcmp(argv[i], "-sf")) {
scale_factor = atof(argv[++i]);
} else if (!strcmp(argv[i], "-ni")) {
saveDetected = 0;
} else if (!strcmp(argv[i], "-rs")) {
rocsize = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-w")) {
width = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-h")) {
height = atoi(argv[++i]);
}
}
if (!cascade.load(classifierdir)) {
printf("Unable to load classifier from %s\n", classifierdir);
return 1;
}
strcpy(fullname, infoname);
filename = strrchr(fullname, '\\');
if (filename == NULL) {
filename = strrchr(fullname, '/');
}
if (filename == NULL) {
filename = fullname;
} else {
filename++;
}
info = fopen(infoname, "r");
totaltime = 0.0;
if (info != NULL) {
int x, y, width, height;
Mat img;
int hits, missed, falseAlarms;
int totalHits, totalMissed, totalFalseAlarms;
int found;
float distance;
int refcount;
ObjectPos* ref;
int detcount;
ObjectPos* det;
int error = 0;
int* pos;
int* neg;
pos = (int*) cvAlloc(rocsize * sizeof(*pos));
neg = (int*) cvAlloc(rocsize * sizeof(*neg));
for (i = 0; i < rocsize; i++) {
pos[i] = neg[i] = 0;
}
printf("+================================+======+======+======+\n");
printf("| File Name | Hits |Missed| False|\n");
printf("+================================+======+======+======+\n");
fprintf(resultados,
"+================================+======+======+======+\n");
fprintf(resultados,
"| File Name | Hits |Missed| False|\n");
fprintf(resultados,
"+================================+======+======+======+\n");
//fprintf (resultados, "%d\n",framesCnt);
totalHits = totalMissed = totalFalseAlarms = 0;
while (!feof(info)) {
fscanf(info, "%s %d", filename, &refcount);
img = imread(fullname);
if (!img.data) {
cout << "ow" << endl;
return -1;
}
ref = (ObjectPos*) cvAlloc(refcount * sizeof(*ref));
for (i = 0; i < refcount; i++) {
error = (fscanf(info, "%d %d %d %d", &x, &y, &width, &height)
!= 4);
if (error)
break;
ref[i].x = 0.5F * width + x;
ref[i].y = 0.5F * height + y;
ref[i].width = sqrt(0.5F * (width * width + height * height));
ref[i].found = 0;
ref[i].neghbors = 0; //in the new cascade, where to get the neighbors?
}
vector<Rect> obj_detectados;
Rect retang;
if (!error) {
totaltime -= time(0);
cascade.detectMultiScale(img, obj_detectados, scale_factor, 4, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
// |CV_HAAR_DO_ROUGH_SEARCH
| CV_HAAR_SCALE_IMAGE, Size(25, 15));
totaltime += time(0);
if (obj_detectados.size() == 0) {
detcount = 0;
} else {
detcount = obj_detectados.size();
}
det = (detcount > 0) ?
((ObjectPos*) cvAlloc(detcount * sizeof(*det))) : NULL;
hits = missed = falseAlarms = 0;
for (vector<Rect>::const_iterator r = obj_detectados.begin();
r != obj_detectados.end(); r++, i++) {
Point r1, r2;
r1.x = (r->x);
r1.y = (r->y);
r2.x = (r->x + r->width);
r2.y = (r->y + r->height);
retang.x = r1.x;
retang.y = r1.y;
retang.width = abs(r2.x - r1.x);
retang.height = abs(r2.y - r1.y);
if (saveDetected) {
rectangle(img, retang, Scalar(0, 0, 255), 3, CV_AA);
}
det[i].x = 0.5F*r->width + r->x;
det[i].y = 0.5F*r->height + r->y;
det[i].width = sqrt(0.5F * (r->width * r->width
+ r->height * r->height));
det[i].neghbors = 1; // i don't know if it will work...
// det[i].neghbors = r.neighbors; --- how to do it in the new version??
found = 0;
for (j = 0; j < refcount; j++) {
distance = sqrtf( (det[i].x - ref[j].x) * (det[i].x - ref[j].x) +
(det[i].y - ref[j].y) * (det[i].y - ref[j].y) );
//cout << distance << endl;
if( (distance < ref[j].width * maxPosDiff) &&
(det[i].width > ref[j].width / maxSizeDiff) &&
(det[i].width < ref[j].width * maxSizeDiff) )
{
ref[j].found = 1;
ref[j].neghbors = MAX( ref[j].neghbors, det[i].neghbors );
found = 1;
}
}
if (!found) {
falseAlarms++;
neg[MIN(det[i].neghbors, rocsize - 1)]++;
//neg[MIN(0, rocsize - 1)]++;
}
}
//imshow("teste", img);
if (saveDetected) {
//strcpy(detfilename, detname);
//strcat(detfilename, filename);
//strcpy(filename, detfilename);
imwrite(fullname, img);
//cvvSaveImage(fullname, img);
}
for (j = 0; j < refcount; j++) {
if (ref[j].found) {
hits++;
//pos[MIN(0, rocsize - 1)]++;
pos[MIN(ref[j].neghbors, rocsize - 1)]++;
} else {
missed++;
}
}
totalHits += hits;
totalMissed += missed;
totalFalseAlarms += falseAlarms;
printf("|%32.64s|%6d|%6d|%6d|\n", filename, hits, missed,
falseAlarms);
//printf("+--------------------------------+------+------+------+\n");
fprintf(resultados, "|%32.64s|%6d|%6d|%6d|\n", filename, hits,
missed, falseAlarms);
//fprintf(resultados,
// "+--------------------------------+------+------+------+\n");
fflush(stdout);
if (det) {
cvFree( &det);
det = NULL;
}
} /* if( !error ) */
//char c = (char) waitKey(10);
// if (c == 27)
// exit(0);
cvFree( &ref);
}
fclose(info);
printf("|%32.32s|%6d|%6d|%6d|\n", "Total", totalHits, totalMissed,
totalFalseAlarms);
fprintf(resultados, "|%32.32s|%6d|%6d|%6d|\n", "Total", totalHits,
totalMissed, totalFalseAlarms);
printf("+================================+======+======+======+\n");
fprintf(resultados,
"+================================+======+======+======+\n");
//printf("Number of stages: %d\n", nos);
//printf("Number of weak classifiers: %d\n", numclassifiers[nos - 1]);
printf("Total time: %f\n", totaltime);
fprintf(resultados, "Total time: %f\n", totaltime);
/* print ROC to stdout */
for (i = rocsize - 1; i > 0; i--) {
pos[i - 1] += pos[i];
neg[i - 1] += neg[i];
}
//fprintf(stderr, "%d\n", nos);
for (i = 0; i < rocsize; i++) {
fprintf(stderr, "\t%d\t%d\t%f\t%f\n", pos[i], neg[i],
((float) pos[i]) / (totalHits + totalMissed),
((float) neg[i]) / (totalHits + totalMissed));
}
cvFree( &pos);
cvFree( &neg);
}
return 0;
}
My doubt is about the det[i].neghbors = r.neighbors; in the old performance.cpp. How I retrieve the neighbors in this new version?
Anyone could help me to convert opencv_performance to run the new cascades from opencv_traincascade?
Many thanks!