RtAudio: understanding frame count vs buffer size - c++

Looking at the duplex example from the documentation of RtAudio, I do not understand why the number of frames has to be multiplied by 8 to get the good buffer size to copy.
In the example there is bufferBytes = bufferFrames * 2 * 4;. I imagine the * 2 refers to the number of channels, but I see no reason for the * 4.
Whole example:
#include "RtAudio.h"
#include <iostream>
#include <cstdlib>
#include <cstring>
// Pass-through function.
int inout( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status, void *data )
{
// Since the number of input and output channels is equal, we can do
// a simple buffer copy operation here.
if ( status ) std::cout << "Stream over/underflow detected." << std::endl;
unsigned int *bytes = (unsigned int *) data;
memcpy( outputBuffer, inputBuffer, *bytes );
return 0;
}
int main()
{
RtAudio adac;
if ( adac.getDeviceCount() < 1 ) {
std::cout << "\nNo audio devices found!\n";
exit( 0 );
}
// Set the same number of channels for both input and output.
unsigned int bufferBytes, bufferFrames = 512;
RtAudio::StreamParameters iParams, oParams;
iParams.deviceId = 0; // first available device
iParams.nChannels = 2;
oParams.deviceId = 0; // first available device
oParams.nChannels = 2;
try {
adac.openStream( &oParams, &iParams, RTAUDIO_SINT32, 44100, &bufferFrames, &inout, (void *)&bufferBytes );
}
catch ( RtAudioError& e ) {
e.printMessage();
exit( 0 );
}
// THIS HERE...
//
bufferBytes = bufferFrames * 2 * 4; // <---- WHY * 4??
//
//
try {
adac.startStream();
char input;
std::cout << "\nRunning ... press <enter> to quit.\n";
std::cin.get(input);
// Stop the stream.
adac.stopStream();
}
catch ( RtAudioError& e ) {
e.printMessage();
goto cleanup;
}
cleanup:
if ( adac.isStreamOpen() ) adac.closeStream();
return 0;
}

Related

Getting memory usage of program from another program in C++ (LINUX)

I would like to measure the maximum memory usage of abc.exe on random tests generated by gen.exe. How could I do that?
My code that runs abc.exe on tests from gen.exe looks like this:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int i = 0;
while (true)
{
string si = to_string(i);
cout << i << "\n";
if (system(("echo " + si + "| ./gen.exe > test.in").c_str())) // gen.exe is test generator
{
cout << "gen error\n";
break;
}
if (system(("./abc.exe < test.in > a.out"))) // abc.exe is the program I want to test
{
cout << "abc error\n";
break;
}
i++;
}
}
I know that i can use time -v ./abc.exe but then the used memory is printed in the terminal but I'd like to be able to save it to a variable.
You can use getrusage( RUSAGE_CHILDREN, ... ) to obtain the maximum resident memory. Note that this call will return the maximum memory used by the biggest child at that point in time.
In the example below I used boost::process because it gives better control but it's up to you to use std::system or not, works the same way.
#include <string>
#include <cstdint>
#include <string.h>
#include <iostream>
#include <boost/process/child.hpp>
#include <sys/resource.h>
namespace bp = boost::process;
int parent( const std::string& exename )
{
// Loop from 0 to 10 megabytes
for ( int j=0; j<10; ++j )
{
// Command name is the name of this executable plus one argument with size
std::string gencmd = exename + " " + std::to_string(j);
// Start process
bp::child child( gencmd );
// Wait for it to allocate memory
sleep(1);
// Query the memory usage at this point in time
struct rusage ru;
getrusage( RUSAGE_CHILDREN, &ru );
std::cerr << "Loop:" << j << " mem:"<< ru.ru_maxrss/1024. << " MB" << std::endl;
// Wait for process to quit
child.wait();
if ( child.exit_code()!=0 )
{
std::cerr << "Error executing child:" << child.exit_code() << std::endl;
return 1;
}
}
return 0;
}
int child( int size ) {
// Allocated "size" megabites explicitly
size_t memsize = size*1024*1024;
uint8_t* ptr = (uint8_t*)malloc( memsize );
memset( ptr, size, memsize );
// Wait for the parent to sample our memory usage
sleep( 2 );
// Free memory
free( ptr );
return 0;
}
int main( int argc, char* argv[] )
{
// Without arguments, it is the parent.
// Pass the name of the binary
if ( argc==1 ) return parent( argv[0] );
return child( std::atoi( argv[1] ) );
}
It prints
$ ./env_test
Loop:0 mem:0 MB
Loop:1 mem:3.5625 MB
Loop:2 mem:4.01953 MB
Loop:3 mem:5.05469 MB
Loop:4 mem:6.04688 MB
Loop:5 mem:7.05078 MB
Loop:6 mem:7.78516 MB
Loop:7 mem:8.97266 MB
Loop:8 mem:9.82031 MB
Loop:9 mem:10.8867 MB
If you cannot use boost libraries, you'd got to work a little more but it is still feasible.
If you just want to know the maximum size ever of your children processes then the following works with std::system:
#include <cstdio>
#include <string>
#include <iostream>
#include <sstream>
#include <string.h>
#include <unistd.h>
#include <sys/resource.h>
int main(int argc, char* argv[]) {
if (argc > 1) {
size_t size = ::atol(argv[1]);
size_t memsize = size * 1024 * 1024;
void* ptr = ::malloc(memsize);
memset(ptr, 0, memsize);
::sleep(2);
::free(ptr);
return 0;
}
for (int j = 0; j < 10; ++j) {
std::ostringstream cmd;
cmd << argv[0] << " " << j;
int res = std::system(cmd.str().c_str());
if (res < 0) {
fprintf(stderr, "ERROR system: %s\n", strerror(errno));
break;
}
struct rusage ru;
res = getrusage(RUSAGE_CHILDREN, &ru);
size_t maxmem = ru.ru_maxrss;
fprintf(stderr, "Loop:%d MaxMem:%ld\n", j, maxmem);
}
return 0;
}
It prints
Loop:0 MaxMem:3552
Loop:1 MaxMem:4192
Loop:2 MaxMem:5148
Loop:3 MaxMem:6228
Loop:4 MaxMem:7364
Loop:5 MaxMem:8456
Loop:6 MaxMem:9120
Loop:7 MaxMem:10188
Loop:8 MaxMem:11324
Loop:9 MaxMem:12256
However if you want to keep track of the memory usage during the child process execution you cannot use std::system(). First, you need to call fork() to spawn a new process and then execv() to execute a bash command.
#include <string>
#include <cstdint>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include <sys/resource.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <vector>
int parent(const std::string& exename) {
// Loop from 0 to 10 megabytes
for (int j = 0; j < 10; ++j) {
// Command name is the name of this executable plus one argument with size
std::string gencmd = exename + " " + std::to_string(j);
// Start process
pid_t pid = fork();
if (pid == 0) { // child
const char* args[] = {"/bin/bash", "-c", gencmd.c_str(), (char*)0};
int res = execv("/bin/bash", (char**)args);
// Should never return
std::cerr << "execv error: " << strerror(errno) << std::endl;
return 1;
}
// parent
long maxmem = 0;
while (true) {
int status;
pid_t rid = ::waitpid(pid, &status, WNOHANG);
if (rid < 0) {
if (errno != ECHILD) {
std::cerr << "waitpid:" << strerror(errno) << std::endl;
return 2;
}
break;
}
if (rid == pid) {
if (WIFEXITED(pid)) {
break;
}
}
// Wait for it to allocate memory
usleep(10000);
// Query the memory usage at this point in time
struct rusage ru;
int res = getrusage(RUSAGE_CHILDREN, &ru);
if (res != 0) {
if (errno != ECHILD) {
std::cerr << "getrusage:" << errno << strerror(errno) << std::endl;
}
break;
}
if (maxmem < ru.ru_maxrss) {
maxmem = ru.ru_maxrss;
}
}
std::cerr << "Loop:" << j << " mem:" << maxmem / 1024. << " MB" << std::endl;
}
return 0;
}
int child(int size) {
// Allocated "size" megabites explicitly
size_t memsize = size * 1024 * 1024;
uint8_t* ptr = (uint8_t*)malloc(memsize);
memset(ptr, size, memsize);
// Wait for the parent to sample our memory usage
sleep(2);
// Free memory
free(ptr);
return 0;
}
int main(int argc, char* argv[]) {
// Without arguments, it is the parent.
// Pass the name of the binary
if (argc == 1) return parent(argv[0]);
return child(std::atoi(argv[1]));
}
The result on my machine is:
$ ./fork_test
Loop:0 mem:3.22656 MB
Loop:1 mem:3.69922 MB
Loop:2 mem:4.80859 MB
Loop:3 mem:5.92578 MB
Loop:4 mem:6.87109 MB
Loop:5 mem:8.05469 MB
Loop:6 mem:8.77344 MB
Loop:7 mem:9.71875 MB
Loop:8 mem:10.7422 MB
Loop:9 mem:11.6797 MB
There is a video about this post.

Why do changes to buffer in thread not be reflected in buffer on mainThread?

I'm trying to receive audio from the soundcard via RtAudio Api. It has a callback function that gets called once the audio has enough bytes received and the user can then copy the data to a custom object. This custom object can be sent to the callback via pointer. My class that encapsulates RtAudio looks like this:
class Audio {
private:
AudioConfiguration config;
AudioData data;
RtAudio* rt;
// the void* d is the casted AudioData-object
static int input( void*, void* inputBuffer, unsigned int bufferSize, double, RtAudioStreamStatus status, void* d );
void openStream( RtAudio::StreamParameters& params, RtAudio::StreamOptions& options, AudioConfiguration& config );
bool isDeviceOk();
public:
// ctor & dtor
Audio( AudioConfiguration& c );
~Audio();
// copy ctor & assignment
Audio( const Audio& other );
Audio& operator=( const Audio& a );
// move ctor & assignment
Audio( Audio&& other );
Audio& operator=( Audio&& a);
AudioConfiguration& getConfiguration();
AudioData& getData();
void start();
void stop();
};
This is the implementation of the static function that gets called from inside the audio thread
int Audio::input( void*, void* inputBuffer, unsigned int bufferSize, double, RtAudioStreamStatus status, void* d ){
if( status == RTAUDIO_INPUT_OVERFLOW )
std::cout << "Audio Thread: Input overflow detected." << std::endl;
//std::cout << "Audio Thread: Received input from soundcard" << std::endl;
float* in = static_cast<float*>( inputBuffer );
AudioData* data = static_cast<AudioData*>( d );
boost::lock_guard<boost::mutex> lock{data->getMutex()};
unsigned int i = 0;
while( i < bufferSize ){
data->getBuffer().push_back( *in );
in++;
i++;
}
return 0;
}
The custom object that I share between the threads is of the class AudioData, which looks like this:
class AudioData {
private:
boost::circular_buffer<float> buffer;
boost::mutex mutex;
public:
AudioData();
~AudioData();
boost::circular_buffer<float>& getBuffer();
boost::mutex& getMutex();
};
The audio-object gets embedded in a Recorder-Object, which then reads the buffer in the AudioData member variable of Audio.
typedef boost::container::vector<boost::circular_buffer<float>> Buffers;
class Recorder {
private:
Audio audio;
Buffers buffers;
/*
* Reads n samples per channel from audio buffers to NUM_CHANNELS distinct buffers
* When done, it returns the number of samples read into each channel
* Why? We want to keep audio buffer to be locked as minimal time as possible
*/
unsigned int read( unsigned int samples );
/*
* Deletes n samples from channel buffer
* When done, it returns the number of samples deleted
*/
unsigned int deleteBegin( unsigned int ch, unsigned int samples );
/*
* Detects the trigger on TRIGGER_CHANNEL
* Returns true, if trigger was found and its position
*/
bool detectTrigger( unsigned int* pos );
public:
Recorder( AudioConfiguration& c );
Recorder( Audio&& a );
boost::container::vector<float> record( RecorderConfiguration& config );
};
The function record(..) looks like this:
boost::container::vector<float> Recorder::record( RecorderConfiguration& config ){
AudioConfiguration audioConfig = audio.getConfiguration();
unsigned int length = ( audioConfig.fs * config.length ) / 1000;
boost::container::vector<float> recording;
recording.resize( length );
// Tell Audio to start recording
audio.start();
// State
unsigned int times = 0; // Count averages
unsigned int left = length; // Samples left on current average
bool triggered = false; // Trigger has been read
while( true ){
// Read into local buffer
unsigned int samplesToRead = length / 10;
unsigned int samplesRead = read( samplesToRead );
// if not enough samples, wait for more
if( samplesRead < 100 )
continue;
// Actual logic
unsigned int triggerPos = 0;
if( !triggered && detectTrigger( &triggerPos ) ){
std::cout << "Recorder: Trigger detected." << std::endl;
triggered = true;
// delete everything that comes before trigger on both channels
for( unsigned int i = 0 ; i < NUM_CHANNELS ; i++ ){
deleteBegin( i, triggerPos - 1);
}
}
// Copy from buffer if trigger was found beforehand
if( triggered ){
boost::circular_buffer<float>& buffer = buffers[ EEG_CHANNEL ];
unsigned int samplesToCopy = buffer.size();
if( samplesToCopy > left )
samplesToCopy = left;
for( unsigned int i = 0 ; i < samplesToCopy ; i++ ){
recording[ length - left ] = recording[ left - left ] + buffer.front();
buffer.pop_front();
left--;
}
}
// current average done
if( left <= 0 ){
// increment times
times++;
// check if recording is done
if( times >= config.times )
break;
// if not
else {
triggered = false;
left = length;
}
}
}
// Stop receiving input from audio
audio.stop();
return recording;
}
I read that the heap is the place to hold data that is shared between threads, but in the example by rtaudio they use a global variable that gets allocated on the stack for pushing the data to Link. So I am a little bit confused. Help would be gladly accepted!
Edit: When i debug my app. I can see that the input function of the audio-thread gets called and it writes to the buffer. Also the record function works as expected. Only the buffer (of AudioData) does not seem to have any data in it...
Edit2: Here is the code where I register the callback in the rtaudio api.
void Audio::openStream( RtAudio::StreamParameters& params, RtAudio::StreamOptions& options, AudioConfiguration& config ){
try {
rt->openStream( nullptr, &params, RTAUDIO_FLOAT32, config.fs, &config.bufferSize, &this->input, &data, &options, nullptr );
} catch( RtAudioError& e ){
std::cout << "Audio::openStream(): Cannot open stream." << std::endl;
throw e;
}
}

portaudio only taking one sample?

I am currently working with portaudio with an application that records, and I seem to have some issues collecting the samples. From what I can see is only one sample being stored, and the callback is only being called once, and that is it, even though the variable NUM_OF_SECONDS is set to 30 seconds.
I currently running out of ideas of what I can test, and how I can debug this, so I've come here, any suggestions to how I can debug my problem?
Here is the code:
main.cpp:
#include <record.h>
int main()
{
record somethis;
somethis.start_record();
return 0;
}
record.h
#pragma once
#include <iostream> // Functionality: COUT
#include "portaudio.h"
#include <stdio.h>
#include <stdlib.h>
#include <chrono> //Functionality: Sleep
#include <thread> //Functionality: Sleep
#include <algorithm> //Functionality: fill_n
#define SAMPLE_RATE (44100)
typedef float SAMPLE;
#define NUM_SECONDS 30
#define NUM_CHANNELS 2
#define SAMPLE_SILENCE 0.0f
#define PA_SAMPLE_TYPE paFloat32
#define FRAMES_PER_BUFFER (512)
#define TRUE (1==1)
#define FALSE (!TRUE)
#define WRITE_TO_FILE TRUE
typedef struct
{
int frameIndex;
int maxFrameindex;
SAMPLE *recordedSamples;
}
paTestData;
class record {
public:
record();
void start_record();
private:
PaStreamParameters inputParameters,
outputParameters;
PaStream* stream;
PaError err = paNoError;
paTestData data;
int totalFrames;
int numSamples;
int numBytes;
SAMPLE max, val;
double average;
int recordCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags, void *userData);
static int recordCallbackSub(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags, void *userData)
{
auto pThis = reinterpret_cast<record*>(userData); // get back the this pointer.
return pThis->recordCallback( inputBuffer, outputBuffer,framesPerBuffer, timeInfo,statusFlags, nullptr);
}
};
record.cpp
#include "record.h"
record::record()
{
std::cout << "Record object made" << std::endl;
std::cout << "Portaudio Version: " << Pa_GetVersion() << std::endl;
this->data.maxFrameindex = this->totalFrames = NUM_SECONDS * SAMPLE_RATE;
this->data.frameIndex = 0;
this->numSamples = this->totalFrames * NUM_CHANNELS;
numBytes = numSamples * sizeof(SAMPLE);
this->data.recordedSamples = new SAMPLE[numSamples]; /* From now on, recordedSamples is initialised. */
if( this->data.recordedSamples == NULL )
{
std::cout << "Could not allocate record array" << std::endl;
exit(1);
}
for(int i=0; i<numSamples; i++ )
{
this->data.recordedSamples[i] = 0;
}
int err = Pa_Initialize();
if( err == paNoError )
{
std::cout << "No error in init" << std::endl;
std::cout << "PortAudio init: "<< Pa_GetErrorText( err ) << std::endl;
}
else
{
printf( "PortAudio error: %s\n", Pa_GetErrorText( err ) );
exit(1);
}
this->inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (this->inputParameters.device == paNoDevice) {
std::cout << "Error: No default input device" << std::endl;
exit(1);
}
this->inputParameters.channelCount = 1; /* stereo input */
this->inputParameters.sampleFormat = PA_SAMPLE_TYPE;
this->inputParameters.suggestedLatency = Pa_GetDeviceInfo( this->inputParameters.device )->defaultLowInputLatency;
this->inputParameters.hostApiSpecificStreamInfo = NULL;
std::cout << "Device name: " <<Pa_GetDeviceInfo(this->inputParameters.device)->name << std::endl;
std::cout << "Max inputChannels: " <<Pa_GetDeviceInfo(this->inputParameters.device)->maxInputChannels << std::endl;
}
int record::recordCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags, void *userData)
{
std::cout << "Callback called" << std::endl;
this->data = (paTestData&) userData;
const SAMPLE *rptr = (const SAMPLE*)inputBuffer;
SAMPLE *wptr = &this->data.recordedSamples[this->data.frameIndex * NUM_CHANNELS];
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = this->data.maxFrameindex - this->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(int i=0; i<framesToCalc; i++ )
{
*wptr++ = SAMPLE_SILENCE; /* left */
if( NUM_CHANNELS == 2 ) *wptr++ = SAMPLE_SILENCE; /* right */
}
}
else
{
for(int i=0; i<framesToCalc; i++ )
{
*wptr++ = *rptr++; /* left */
if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++; /* right */
}
}
this->data.frameIndex += framesToCalc;
return finished;
}
void record::start_record()
{
err = Pa_OpenStream(
&this->stream,
&this->inputParameters,
NULL, /* &outputParameters, */
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
&record::recordCallbackSub,
this );
if( err != paNoError )
{
std::cout << "Something wrong - open_stream check" << std::endl;
std::cout << "PortAudio error: "<< Pa_GetErrorText( err ) << std::endl;
exit(1);
}
this->err = Pa_StartStream( this->stream );
if( err != paNoError )
{
std::cout << "Something wrong in stream check" << std::endl;
std::cout << "PortAudio error: "<< Pa_GetErrorText( err ) << std::endl;
exit(1);
}
std::cout << "Waiting for playback to finish" << std::endl;
while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
{
Pa_Sleep(1000);
printf("index = %d\n", this->data.frameIndex ); fflush(stdout);
}
if( err < 0 )
{
std::cout << "error check with isStreamActive - something wrong" << std::endl;
std::cout << "PortAudio error: "<< Pa_GetErrorText( err ) << std::endl;
exit(1);
}
err = Pa_CloseStream( stream );
if( err != paNoError )
{
std::cout << "error check with close_stream- something wrong" << std::endl;
std::cout << "PortAudio error: "<< Pa_GetErrorText( err ) << std::endl;
exit(1);
}
std::cout << "Number of entries: " << sizeof(this->data.recordedSamples)/sizeof(this->data.recordedSamples[0]) << std::endl;
/* Measure maximum peak amplitude. */
max = 0;
average = 0.0;
for(int i=0; i<numSamples; i++ )
{
val = this->data.recordedSamples[i];
std::cout << "i: " << i << " : "<< val << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if( val < 0 ) val = -val; /* ABS */
if( val > max )
{
max = val;
}
average += val;
}
average = average / (double)numSamples;
std::cout<<"sample max amplitude = " << max << std::endl;
std::cout<<"sample average = " << average << std::endl;
if (WRITE_TO_FILE)
{
FILE *fid;
fid = fopen("recorded.wav", "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");
}
}
std::cout << "Everythin done!" << std::endl;
}
Update:
I've from some debugging notices that the callback is only being called once, and after it returns, becomes the stream inactive, hence making the it impossible to make calls to the callback function. Why does the stream become inactive?
Your first callback
static int recordCallbackSub(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags, void *userData)
{
auto pThis = reinterpret_cast<record*>(userData); // get back the this pointer.
return pThis->recordCallback( inputBuffer, outputBuffer,framesPerBuffer, timeInfo,statusFlags, nullptr);
}
calls your second callback
int record::recordCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags, void *userData)
{
std::cout << "Callback called" << std::endl;
this->data = (paTestData&) userData;
....
}
with the userData parameter set to nullptr. You then cast the nullptr into a paTestData& and set your data member variable to the result, which I suspect you didn't intend to do.
Delete the this->data = (paTestData&) userData; line.

Why the recorded audio data only use half of the buffer (WaveIn)?

I'm trying to record audio data from the microphone and save in files. The problem is that the wavein device only uses half the buffer specified in the wave header. In particular, only first 2000 points in the file from the audio, the rest of the file reads like the following
-12851
-12851
-12851
-12851
.....
Not clear what goes wrong. What I find is that if I change the following line of code from
_header[i].dwBufferLength = bpbuff;
to
_header[i].dwBufferLength = 2*bpbuff;
then all 4000 values are indeed the audio input. But obviously this is not the right way to get the problem fixed. Any thoughts?
Here's the full code:
#include "stdafx.h"
#include <Windows.h>
#pragma comment(lib, "winmm.lib")
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
HANDLE hEvent_BufferReady;
#define Samplerate 2000
#define nSec 3
BOOL BufferReady;
enum { NUM_BUF = 8 };
int _iBuf;
int prevBuf;
void CALLBACK myWaveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
WAVEHDR *pHdr=NULL;
switch(uMsg)
{
case WIM_CLOSE:
cout << "waveInProc()... WIM_CLOSE" << endl;
break;
case WIM_DATA:
{
cout << "waveInProc()... WIM_DATA : " <<endl;
SetEvent(hEvent_BufferReady);
}
break;
case WIM_OPEN:
cout << "waveInProc()... WIM_OPEN" << endl;
break;
default:
break;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
hEvent_BufferReady=CreateEvent(NULL,FALSE, FALSE, NULL);
WAVEFORMATEX pFormat;
pFormat.wFormatTag = WAVE_FORMAT_PCM; // simple, uncompressed format
pFormat.nChannels = 1; // 1=mono, 2=stereo
pFormat.nSamplesPerSec = Samplerate; // 44100
pFormat.wBitsPerSample = 16; // 16 for high quality, 8 for telephone-grade
pFormat.nBlockAlign = pFormat.nChannels*pFormat.wBitsPerSample/8;
pFormat.nAvgBytesPerSec = (pFormat.nSamplesPerSec)*(pFormat.nChannels)*(pFormat.wBitsPerSample)/8;
pFormat.cbSize=0;
HWAVEIN hWaveIn;
unsigned long result;
WAVEHDR _header [NUM_BUF];
short int *_pBuf;
size_t bpbuff = (pFormat.nSamplesPerSec) * (pFormat.nChannels) * (pFormat.wBitsPerSample)/8;
result = waveInOpen(&hWaveIn, WAVE_MAPPER,&pFormat, (DWORD)myWaveInProc, 0L, CALLBACK_FUNCTION);
_pBuf = new short int [bpbuff * NUM_BUF];
// initialize all headers in the queue
for ( int i = 0; i < NUM_BUF; i++ )
{
_header[i].lpData = (LPSTR)&_pBuf [i * bpbuff];
_header[i].dwBufferLength = bpbuff;
_header[i].dwFlags = 0L;
_header[i].dwLoops = 0L;
waveInPrepareHeader(hWaveIn, & _header[i], sizeof(WAVEHDR));
waveInAddBuffer (hWaveIn, & _header[i], sizeof (WAVEHDR));
}
_iBuf = 0;
int _prevBuf = NUM_BUF - 1;
unsigned char* tempchar;
waveInStart(hWaveIn);
for(int iter=0;iter<5;iter++)
{
do {
} while (!(_header[_iBuf].dwFlags & WHDR_DONE));
waveInUnprepareHeader (hWaveIn, &_header[_iBuf], sizeof (WAVEHDR));
std::ostringstream fn;
fn << "file" << iter << ".txt";
ofstream myfile;
myfile.open (fn.str());
for(int i=0;i<bpbuff;i++)
{
myfile<<_pBuf[_iBuf*bpbuff + i]<<"\n";
}
myfile.close();
int prevBuf = _iBuf - 1;
if (prevBuf < 0)
prevBuf = NUM_BUF - 1;
_header [prevBuf].lpData = (LPSTR)&_pBuf [prevBuf * bpbuff];
_header [prevBuf].dwBufferLength = bpbuff;
_header [prevBuf].dwFlags = 0L;
_header [prevBuf].dwLoops = 0L;
waveInPrepareHeader(hWaveIn, & _header[_iBuf], sizeof(WAVEHDR));
waveInAddBuffer (hWaveIn, & _header[_iBuf], sizeof (WAVEHDR));
++_iBuf;
if (_iBuf == NUM_BUF) _iBuf = 0;
}
waveInClose(hWaveIn);
cout<<"hello"<<endl;
getchar();
CloseHandle(hEvent_BufferReady);
return 0;
}
WAVEHDR::dwBufferLength:
dwBufferLength - Length, in bytes, of the buffer.
Your code:
_pBuf = new short int [bpbuff * NUM_BUF];
// initialize all headers in the queue
for ( int i = 0; i < NUM_BUF; i++ )
{
_header[i].lpData = (LPSTR)&_pBuf [i * bpbuff];
_header[i].dwBufferLength = bpbuff;
Your buffer is bpbuff * sizeof (short int) bytes long. However you route it to the API to get it filled with bpbuff bytes of data only. Hence, the buffer is only filled partially and the rest of it holds uninitialized data (which you see as -12851, see 0xCDCDCDCD).
You need to make it:
_header[i].dwBufferLength = bpbuff * sizeof *_pBuf;

Progress bar during operation in console application

I started working on an encryption application but I seemed to greatly over think how I would get it to show a progress bar as it worked.
the task is simple lSize is the total size od the files being encrypted.
With the following loop in C++
//********** Open file **********
FILE * inFile = fopen (argv[1], "rb");
fseek(inFile , 0 , SEEK_END);
unsigned long lSize = ftell(inFile);
rewind(inFile);
unsigned char *text = (unsigned char*) malloc (sizeof(unsigned char)*lSize);
fread(text, 1, lSize, inFile);
fclose(inFile);
//*********** Encypt ************
unsigned char aesKey[32] = {
/* Hiding this for now */
};
unsigned char *buf;
aes256_context ctx;
aes256_init(&ctx, aesKey);
for (unsigned long i = 0; i < lSize/16; i++) {
buf = text + (i * 16);
aes256_decrypt_ecb(&ctx, buf);
}
aes256_done(&ctx);
//******************************************************
I was wondering how I could display the progress for the for loop while it works.
I know I need to calculate how much is done so far but I do not know how to do so.
What you need is multi-threading. Here is some sample source for a progress bar (from: http://www.cplusplus.com/reference/future/future/)
#include <iostream> // std::cout
#include <future> // std::async, std::future
#include <chrono> // std::chrono::milliseconds
// a non-optimized way of checking for prime numbers:
bool is_prime (int x) {
for (int i=2; i<x; ++i) if (x%i==0) return false;
return true;
}
int main ()
{
// call function asynchronously:
std::future<bool> fut = std::async (is_prime,444444443);
// do something while waiting for function to set future:
std::cout << "checking, please wait";
std::chrono::milliseconds span (100);
while (fut.wait_for(span)==std::future_status::timeout)
std::cout << '.';
bool x = fut.get(); // retrieve return value
std::cout << "\n444444443 " << (x?"is":"is not") << " prime.\n";
return 0;
}