(C++) Music player plays garbage at the beginning - c++

I've created very simple mp3 player in C++ using mpg123 and out123, by following this tutorial: https://www.kasrajamshidi.com/blog/audio. However, I had an issue when the player was starting: for first few seconds it was playing garbage noise. This sound wasn't the same every single time. Sometimes it took longer, sometimes it was almost inaudible.
I thought, it's because I write to the buffer and read from it almost in the same time, so I've modified the code and used circular buffer, where I first read some data and write it to the buffer, then while playing it I write bytes with some offset. Unfortunately the problem remains the same and I'm confused.
Here is my code:
#include <iostream>
#include <mpg123.h>
#include <out123.h>
// If i print messages music starts much smoother...
// (But the problem itself does not disappear).
#define PRINT_BUFFER_STATE false
// Size of the circular buffer.
const int BUFFER_SIZE = 4;
int main(int argc, char **argv)
{
// Initialize mpg123
if(mpg123_init() != MPG123_OK)
return 255;
mpg123_handle *mpg_handle = mpg123_new(nullptr, nullptr);
out123_handle *out_handle = out123_new();
// This buffer is circular. The inxed of point we write is far before
// the place we play from. bytes_written[i] tells us how many bytes
// were written to buffer[i]. This is the number of bytes we need to output,
// when we play from it.
unsigned char **buffer =
(unsigned char **)alloca(sizeof(unsigned char *) * BUFFER_SIZE);
std::size_t *bytes_written =
(std::size_t *)alloca(sizeof(std::size_t) * BUFFER_SIZE);
// These indexes tell us where we do we write bytes,
// and from where do we play them.
int play_buffer = 0;
int write_buffer = 0;
int number_of_clips = 2;
char **clip_path = (char **)alloca(sizeof(char *) * number_of_clips);
clip_path[0] = "/home/mateusz/Music/guitar.mp3";
clip_path[1] = "/home/mateusz/Music/drums.mp3";
for (int clip = 0; clip < number_of_clips; ++clip)
{
// Open a given file with mpg123 (to get format,
// which will then be passed to out device).
mpg123_open(mpg_handle, clip_path[clip]);
// Set format details:
int channels = 0;
int encoding = 0;
long rate = 0;
mpg123_getformat(mpg_handle, &rate, &channels, &encoding);
// Allocate the contets of the circulat buffer.
std::size_t buffer_size = mpg123_outblock(mpg_handle);
for (int i = 0; i < BUFFER_SIZE; ++i)
buffer[i] = (unsigned char *)malloc(sizeof(unsigned char) * buffer_size);
// Start by filling part of the bufer so that the index we write
// is ahead.
for (write_buffer = 0;
write_buffer < BUFFER_SIZE-1;
++write_buffer)
{
mpg123_read(mpg_handle, buffer[write_buffer], buffer_size,
&bytes_written[write_buffer]);
// If there is nothing to read we break the loop.
if (!bytes_written[write_buffer])
break;
}
// Set out handle to the device we'll play from with default parameters.
out123_open(out_handle, nullptr, nullptr);
out123_start(out_handle, rate, channels, encoding);
play_buffer = 0;
// play_buffer should never catch write_buffer unless
// the second one finished its job.
while (write_buffer != play_buffer)
{
#if PRINT_BUFFER_STATE
std::cout << "W: " << write_buffer << " R: " << play_buffer << "\n";
#endif
out123_play(out_handle, buffer[play_buffer],
bytes_written[play_buffer]);
mpg123_read(mpg_handle, buffer[write_buffer], buffer_size,
&bytes_written[write_buffer]);
play_buffer = (play_buffer + 1) % BUFFER_SIZE;
if (bytes_written[write_buffer])
write_buffer = (write_buffer + 1) % BUFFER_SIZE;
}
for (int i = 0; i < BUFFER_SIZE; ++i)
free(buffer[i]);
out123_stop(out_handle);
out123_close(out_handle);
mpg123_close(mpg_handle);
}
out123_del(out_handle);
mpg123_delete(mpg_handle);
mpg123_exit();
return 0;
}
Changing BUFFER_SIZE to really big number doesn't help so the problem is not there. Surprisingly enough when I print some stuff to console it seems to work much smoother. But the problem does not disappear.
My guess is that something is not synchronized, but thats really all I can tell... Should my program sleep in the loop after playing each chunk of sound? Well, I tried to put a sleep command almost everywhere, but it didn't achieve much. There must be something I'm doing wrong but I can't figgure it out. So my question is: how do I prevent my player from playing this terrible sound every time it starts new file?

Related

Decreasing Latency of playing sound using Playsound in C++ (windows)

Currently, we are playing 5 sounds one after another using Wave output and Fetching from the TCP socket. We are now using playBuffer to play the sounds. But there is a latency of playing one sound from another sound to. I don't want any latency in between playing the 5 audio and want to be played immediately. Is there any way to do that in playsound, or can I achieve that using any other library in C++ ? I am currently using a windows system. Would really appreciate some help, Seaching for hours for a solution.
// AudioTask.cpp : Defines the entry point for the console application.
// Adapted from http://www.cplusplus.com/forum/beginner/88542/
#include "stdafx.h"
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <mmsystem.h>
#include <iostream>
#include <fstream>
#include <conio.h>
#include <math.h>
#include <stdint.h>
#define PI 3.14159265
using namespace std;
typedef struct WAV_HEADER1 {
uint8_t RIFF[4]; // = { 'R', 'I', 'F', 'F' };
uint32_t ChunkSize;
uint8_t WAVE[4]; // = { 'W', 'A', 'V', 'E' };
uint8_t fmt[4]; // = { 'f', 'm', 't', ' ' };
uint32_t Subchunk1Size = 16;
uint16_t AudioFormat = 1;
uint16_t NumOfChan = 1;
uint32_t SamplesPerSec = 16000;
uint32_t bytesPerSec = 16000 * 2;
uint16_t blockAlign = 2;
uint16_t bitsPerSample = 16;
uint8_t Subchunk2ID[4]; // = { 'd', 'a', 't', 'a' };
uint32_t Subchunk2Size;
} wav_hdr1;
void playBuffer(short* audioSamplesData1, short* audioSamplesData2, int count)
{
static_assert(sizeof(wav_hdr1) == 44, "");
wav_hdr1 wav;
wav.NumOfChan = 2;
wav.SamplesPerSec = 44100;
wav.bytesPerSec = 176400;
wav.blockAlign = 4;
wav.bitsPerSample = 16;
// Fixed values
wav.RIFF[0] = 'R';
wav.RIFF[1] = 'I';
wav.RIFF[2] = 'F';
wav.RIFF[3] = 'F';
wav.WAVE[0] = 'W';
wav.WAVE[1] = 'A';
wav.WAVE[2] = 'V';
wav.WAVE[3] = 'E';
wav.fmt[0] = 'f';
wav.fmt[1] = 'm';
wav.fmt[2] = 't';
wav.fmt[3] = ' ';
wav.Subchunk2ID[0] = 'd';
wav.Subchunk2ID[1] = 'a';
wav.Subchunk2ID[2] = 't';
wav.Subchunk2ID[3] = 'a';
wav.ChunkSize = (count * 2 * 2) + sizeof(wav_hdr1) - 8;
wav.Subchunk2Size = wav.ChunkSize - 20;
char* data = new char[44 + (count * 2 * 2)];
memcpy(data, &wav, sizeof(wav));
int index = sizeof(wav);
//constexpr double max_amplitude = 32766;
for (int i = 0; i < count; i++)
{
short value = audioSamplesData1 ? audioSamplesData1[i] : 0;
memcpy(data + index, &value, sizeof(short));
index += sizeof(short);
value = audioSamplesData2 ? audioSamplesData2[i] : 0;
memcpy(data + index, &value, sizeof(short));
index += sizeof(short);
}
PlaySound((char*)data, GetModuleHandle(0), SND_MEMORY | SND_SYNC);
}
void performAction(short audioSamplesData1[], short audioSamplesData2[], int count)
{
playBuffer(audioSamplesData1, audioSamplesData1, count);
playBuffer(audioSamplesData2, audioSamplesData2, count);
playBuffer(audioSamplesData1, NULL, count);
playBuffer(NULL, audioSamplesData2, count);
playBuffer(audioSamplesData1, audioSamplesData2, count);
}
class Wave {
public:
Wave(char * filename);
~Wave();
void play(bool async = true);
bool isok();
private:
char * buffer;
bool ok;
HINSTANCE HInstance;
int numberOfAudioBytes;
};
Wave::Wave(char * filename)
{
ok = false;
buffer = 0;
HInstance = GetModuleHandle(0);
numberOfAudioBytes = 0;
ifstream infile(filename, ios::binary);
if (!infile)
{
std::cout << "Wave::file error: " << filename << std::endl;
return;
}
infile.seekg(0, ios::end); // get length of file
int length = infile.tellg();
buffer = new char[length]; // allocate memory
infile.seekg(0, ios::beg); // position to start of file
infile.read(buffer, length); // read entire file
std::cout << "Number of elements in buffer : " << length << std::endl;
numberOfAudioBytes = length;
infile.close();
ok = true;
}
Wave::~Wave()
{
PlaySound(NULL, 0, 0); // STOP ANY PLAYING SOUND
delete[] buffer; // before deleting buffer.
}
void Wave::play(bool async)
{
if (!ok)
return;
// Create two arrays of sound data to use as a test for performing the task we need to do.
const int SAMPLE_RATE = 44100; // 44.1 kHz
const int FILE_LENGTH_IN_SECONDS = 3;
const int NUMBER_OF_SAMPLES = SAMPLE_RATE*FILE_LENGTH_IN_SECONDS; // Number of elements of audio data in the array, 132300 in this case.
std::cout << "NUMBER_OF_SAMPLES : " << NUMBER_OF_SAMPLES << std::endl;
short audioSamplesData_A[NUMBER_OF_SAMPLES];
short audioSamplesData_B[NUMBER_OF_SAMPLES];
float maxVolume = 32767.0; // 2^15 - 10.0
float frequencyHz_A = 500.0;
float frequencyHz_B = 250.0;
for (int i = 0; i < NUMBER_OF_SAMPLES; i++)
{
float pcmValue_A = sin(i*frequencyHz_A / SAMPLE_RATE * PI * 2);
float pcmValue_B = sin(i*frequencyHz_B / SAMPLE_RATE * PI * 2);
short pcmValueShort_A = (short)(maxVolume * pcmValue_A);
short pcmValueShort_B = (short)(maxVolume * pcmValue_B);
//short pcmValueShort_B = (short)(0.5*maxVolume*(pcmValue_A + pcmValue_B));
audioSamplesData_A[i] = pcmValueShort_A; // This is what you need to play.
audioSamplesData_B[i] = pcmValueShort_B; // This is what you need to play.
// waveData += pack('h', pcmValueShort_A) - Python code from Python equivalent program, perhaps we need something similar.
// See enclosed "Py Mono Stereo.py" file or visit https://swharden.com/blog/2011-07-08-create-mono-and-stereo-wave-files-with-python/
}
// The task that needs to be done for this project:
// The audio data is available in the form of an array of shorts (audioSamplesData_A and audioSamplesData_B created above).
// What needs to happen is this audio data (audioSamplesData_A and audioSamplesData_B) must each be played so we can hear them.
// When this task is over, there will be no need for any WAV file anywhere, the goal is NOT to produce a WAV file. The goal is
// to take the audio data in the form of audioSamplesData_A and play it from memory somehow.
// We need to take the input data (audioSamplesData_A and audioSamplesData_B) and play the same sounds that the 5 WAV files are currently playing, but
// in the end, we will no longer need those WAV files.
// You do NOT need to create any new files.
// In the end, you do not need to read any files either.
// In the final project, all you will need is this current main.cpp file. You run main.cpp and you hear the 5 sounds.
// The 5 sounds, are created BY C++ here in this file (see loop above).
// Display the first 100 elements for one of the audio samples array
for (int i = 0; i < 100; i++)
{
//std::cout << "i = " << i << ", audioSamplesData_B[i] : " << audioSamplesData_B[i] << std::endl;
}
// Display the first 100 elements for the serialized buffer of WAV header data + some audio data, all coming from one of the WAV files on the disk.
for (int i = 0; i < 100; i++) // Last 6 elements is where audio data begins. First 44 elements are WAV header data.
{
//std::cout << "i = " << i << ", buffer[i] : " << (int) buffer[i] << std::endl;
}
performAction(audioSamplesData_A, audioSamplesData_B, NUMBER_OF_SAMPLES);
// Play the sample sound, the one obtained from the WAV file on the disk, not the one created from the audio samples created above.
//PlaySound((char*)(&audioSamplesData_A[0]), HInstance, SND_MEMORY | SND_SYNC);
//PlaySound((char*)audioSamplesData_B, HInstance, SND_MEMORY | SND_SYNC);
//PlaySound((char*)audioSamplesData_AB, HInstance, SND_MEMORY | SND_SYNC);
//PlaySound((char*)buffer, HInstance, SND_MEMORY | SND_SYNC);
}
bool Wave::isok()
{
return ok;
}
int main(int argc, char *argv[]) {
std::cout << "Trying to play sound ...\n";
// Load the WAV files from them from the disk. These files are here only to help you understand what we need. In the end, we will no longer need them.
Wave outputA("outputA.WAV"); // Audio file equivalent to audioSamplesData_A curve generated in the loop above.
Wave outputB("outputB.WAV"); // Audio file equivalent to audioSamplesData_B curve generated in the loop above.
Wave outputALeftOnly("outputALeftOnly.WAV"); // Audio file that plays sound A on the left only, must be able to take audioSamplesData_A and somehow make it left only.
Wave outputBRightOnly("outputBRightOnly.WAV"); // Audio file that plays sound B on the right only, must be able to take audioSamplesData_B and somehow make it right only.
Wave outputALeftOutputBRight("outputALeftOutputBRight.WAV"); // Must be able to take both audioSamplesData_A and audioSamplesData_B and make it play different sounds in left and right.
// Play the WAV files from the disk, either all of them or a subset of them.
outputA.play(0);
//outputB.play(0);
//outputALeftOnly.play(0);
//outputBRightOnly.play(0);
//outputALeftOutputBRight.play(0);
std::cout << "press key to exit";
while (1) {} // Loop to prevent command line terminal from closing automatically.
return 0;
}

How do I divide binary data into frames in C++?

I need to read a binary file containing several bytes and divide the contents into frames, each consisting of 535 bytes each. The number of frames present in the file is not known at runtime and thus I need to dynamically allocate memory for them. The code below is a snippet and as you can see, I'm trying to create a pointer to an array of bytes (uint8_t) and then increment into the next frame and so on, in the loop that reads the buffered data into the frames. How do I allocate memory at runtime and is this the best way to do the task? Please let me know if there is a more elegant solution. Also, how I manage the memory?
#include <cstdio>
using namespace std;
long getFileSize(FILE *file)
{
long currentPosition, endPosition;
currentPosition = ftell(file);
fseek(file, 0, 2);
endPosition = ftell(file);
fseek(file, currentPosition, 0);
return endPosition;
}
int main()
{
const char *filePath = "C:\Payload\Untitled.bin";
uint8_t *fileBuffer;
FILE *file = NULL;
if((file = fopen(filePath, "rb")) == NULL)
cout << "Failure. Either the file does not exist or this application lacks sufficient permissions to access it." << endl;
else
cout << "Success. File has been loaded." << endl;
long fileSize = getFileSize(file);
fileBuffer = new uint8_t[fileSize];
fread(fileBuffer, fileSize, 1, file);
uint8_t (*frameBuffer)[535];
for(int i = 0, j = 0; i < fileSize; i++)
{
frameBuffer[j][i] = fileBuffer[i];
if((i % 534) == 0)
{
j++;
}
}
struct frame {
unsigned char bytes[535];
};
std::vector<frame> frames;
Now your loop can simply read a frame and push it into frames. No explicit memory management needed: std::vector does that for you.

Best way to read data streams with different package sizes from serial port in c++

I am working on firmware of an ATMEL sensor board (accelerometer and gyro)and trying to read the data in a platform in Ubuntu.
Currently the firmware is like this:
Ubuntu sends a character "D" and the firmware in response sends back 20 bytes of data that ends in "\n" then ubuntu uses serialport_read_until(fd, buff, '\n') and assumes that buff[0] is byte zero and so on.The frequency of acquisition is 200hz.
BUT using this method sometimes I receive corrupted values and it is not working well. Also there are many "Unable to write on serial port" error in ubuntu.
I have found an example code from ATMEL for the firmware and there the data is sent in different packages and continuously (without waiting for the computer to ask for it) the structure is like this:
void adv_data_send_3(uint8_t stream_num, uint32_t timestamp,
int32_t value0, int32_t value1, int32_t value2)
{
/* Define packet format with 3 data fields */
struct {
adv_data_start_t start; /* Starting fields of packet */
adv_data_field_t field [3]; /* 3 data fields */
adv_data_end_t end; /* Ending fields of packet */
} packet;
/* Construct packet */
packet.start.header1 = ADV_PKT_HEADER_1;
packet.start.header2 = ADV_PKT_HEADER_2;
packet.start.length = cpu_to_le16(sizeof(packet));
packet.start.type = ADV_PKT_DATA;
packet.start.stream_num = stream_num;
packet.start.time_stamp = cpu_to_le32(timestamp);
packet.field[0].value = cpu_to_le32(value0);
packet.field[1].value = cpu_to_le32(value1);
packet.field[2].value = cpu_to_le32(value2);
packet.end.crc = 0x00; /* Not used */
packet.end.mark = ADV_PKT_END;
/* Write packet */
adv_write_buf((uint8_t *)&packet, sizeof(packet));
}
but I don't know how I can continuously read the data that is sent in a structure like above.
Sorry if it is a trivial question. I am not a programmer but I need to solve this and I could not find a solution (that I can understand!) after searching for a couple of days.
The reading function I use in linux:
int serialport_read_until(int fd, unsigned char* buf, char until){
char b[1];
int i=0;
do {
int n = read(fd, b, 1); // read a char at a time
if( n==-1) return -1; // couldn't read
if( n==0 ) {
usleep( 1 * 1000 ); // wait 1 msec try again
continue;
}
buf[i] = b[0]; i++;
} while( b[0] != until );
buf[i] = 0; // null terminate the string
return 0;}
The new Reading Func:
// Read the header part
adv_data_start_t start;
serial_read_buf(fd, reinterpret_cast<uint8_t*>(&start), sizeof(start));
// Create a buffer for the data and the end marker
std::vector<uint8_t> data_and_end(start.length - sizeof(start));
// Read the data and end marker
serial_read_buf(fd, data_and_end.data(), data_and_end.size());
// Iterate over the data
size_t num_data_fields = (data_and_end.size() - sizeof(adv_data_end_t)) / sizeof(adv_data_field_t);
adv_data_field_t* fields = reinterpret_cast<adv_data_field_t*>(data_and_end.data());
for (size_t i = 0; i < num_data_fields; i++)
std::cout << "Field #" << (i + 1) << " = " << fields[i].value << '\n';
The data packets that are sent from the firmware:
typedef struct {
uint8_t header1; // header bytes - always 0xFF5A
uint8_t header2; // header bytes - always 0xFF5A
uint16_t length; // packet length (bytes)
uint32_t time_stamp; // time stamp (tick count)
} adv_data_start_t;
typedef struct {
int32_t value; // data field value (3 VALUES)
} adv_data_field_t;
typedef struct {
uint8_t crc; // 8-bit checksum
uint8_t mark; // 1-byte end-of-packet marker
uint16_t mark2; // 2-byte end-of-packet marker (Added to avoid data structure alignment problem)
} adv_data_end_t;
Well you have the length of the packet in the packet "header", so read the header fields (the start structure) in one read, and in a second read you read the data and the end.
If the start and end parts are the same for all packets (which I guess they are), you can easily figure out the amount of data fields after the second read.
Something like this:
// Read the header part
adv_data_start_t start;
adv_read_buf(reinterpret_cast<uint8_t*>(&start), sizeof(start));
// Create a buffer for the data and the end marker
std::vector<uint8_t> data_and_end(start.length - sizeof(start));
// Read the data and end marker
adv_read_buf(data_and_end.data(), data_and_end.size());
// Iterate over the data
size_t num_data_fields = (data_and_end.size() - sizeof(adv_data_end_t)) / sizeof(adv_data_field_t);
adv_data_end_t* fields = reinterpret_cast<adv_data_end_t*>(data_and_end.data());
for (size_t i = 0; i < num_data_fields; i++)
std::cout << "Field #" << (i + 1) << " = " << fields[i] << '\n';
Possible read_buf implementation:
// Read `bufsize` bytes into `buffer` from a file descriptor
// Will block until `bufsize` bytes has been read
// Returns -1 on error, or `bufsize` on success
int serial_read_buf(int fd, uint8_t* buffer, const size_t bufsize)
{
uint8_t* current = buffer;
size_t remaining = bufsize
while (remaining > 0)
{
ssize_t ret = read(fd, current, remaining);
if (ret == -1)
return -1; // Error
else if (ret == 0)
{
// Note: For some descriptors, this means end-of-file or
// connection closed.
usleep(1000);
}
else
{
current += ret; // Advance read-point in buffer
remaining -= ret; // Less data remaining to read
}
}
return bufsize;
}

C++ - Play back a tone generated from a sinusoidal wave

Hey everyone, I'm currently trying to figure out how to play back a tone I have generated using a sinusoidal wave.
Here's my code:
#include <iostream>
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#include <Math.h>
using namespace std;
int main (int argc, char * const argv[]) {
int number = 0;
int i, size;
double const Pi=4*atan(1);
cout << "Enter number of seconds:" << endl;
scanf("%d", &number);
size = 44100*number;
unsigned char buffer [size]; //buffer array
for(i = 0; i < size; i++){
buffer[i] = (char)sin((2*Pi*440)/(44100*i))*127;
}
return 0;
}
Obviously it doesn't do anything at the moment, since I have no idea how to play the buffer.
I don't want to generate a wav file, nor do I want to load one in. I just want to play back the buffer I have generated.
I am currently working on Mac OS X, and have tried using OpenAL methods - however I have found that alut and alu are not part of it anymore and if I try to use it then it turns out that it's all depredated anyway.
I have also tried to include QAudioOutput, but for some reason it does not appear to be anywhere on my Mac.
I just want a simple playback of the tone I've created. Does anyone have anything they can point me to?
Thanks heaps!!!
I've written an example exactly for this. Runs fine with OpenAL under MacOSX and plays smooth sines. Take a look here:
http://ioctl.eu/blog/2011/03/16/openal-sine-synth/
Code is quite short, i guess i can add it here as well for sake of completeness:
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#define CASE_RETURN(err) case (err): return "##err"
const char* al_err_str(ALenum err) {
switch(err) {
CASE_RETURN(AL_NO_ERROR);
CASE_RETURN(AL_INVALID_NAME);
CASE_RETURN(AL_INVALID_ENUM);
CASE_RETURN(AL_INVALID_VALUE);
CASE_RETURN(AL_INVALID_OPERATION);
CASE_RETURN(AL_OUT_OF_MEMORY);
}
return "unknown";
}
#undef CASE_RETURN
#define __al_check_error(file,line) \
do { \
ALenum err = alGetError(); \
for(; err!=AL_NO_ERROR; err=alGetError()) { \
std::cerr << "AL Error " << al_err_str(err) << " at " << file << ":" << line << std::endl; \
} \
}while(0)
#define al_check_error() \
__al_check_error(__FILE__, __LINE__)
void init_al() {
ALCdevice *dev = NULL;
ALCcontext *ctx = NULL;
const char *defname = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
std::cout << "Default device: " << defname << std::endl;
dev = alcOpenDevice(defname);
ctx = alcCreateContext(dev, NULL);
alcMakeContextCurrent(ctx);
}
void exit_al() {
ALCdevice *dev = NULL;
ALCcontext *ctx = NULL;
ctx = alcGetCurrentContext();
dev = alcGetContextsDevice(ctx);
alcMakeContextCurrent(NULL);
alcDestroyContext(ctx);
alcCloseDevice(dev);
}
int main(int argc, char* argv[]) {
/* initialize OpenAL */
init_al();
/* Create buffer to store samples */
ALuint buf;
alGenBuffers(1, &buf);
al_check_error();
/* Fill buffer with Sine-Wave */
float freq = 440.f;
int seconds = 4;
unsigned sample_rate = 22050;
size_t buf_size = seconds * sample_rate;
short *samples;
samples = new short[buf_size];
for(int i=0; i<buf_size; ++i) {
samples[i] = 32760 * sin( (2.f*float(M_PI)*freq)/sample_rate * i );
}
/* Download buffer to OpenAL */
alBufferData(buf, AL_FORMAT_MONO16, samples, buf_size, sample_rate);
al_check_error();
/* Set-up sound source and play buffer */
ALuint src = 0;
alGenSources(1, &src);
alSourcei(src, AL_BUFFER, buf);
alSourcePlay(src);
/* While sound is playing, sleep */
al_check_error();
sleep(seconds);
/* Dealloc OpenAL */
exit_al();
al_check_error();
return 0;
}
Update: I've found OpenAL a bit too limiting for my needs, like I have some problems with low-latency playback as this appears to be not the primary domain of OpenAL. Instead, I've found the very convincing PortAudio: http://www.portaudio.com/
It supports all major platforms (Mac,Win,Unix/ALSA) and looks very good. There is an example for sine playback which is far more sophisticated, yet quite simple. Just download the latest release and find the sine-playback sample at test/patest_sine.c
You will need to go through the OS to play back sounds. It's not as straightforward as you would think. In OSX, you will need to go through CoreAudio.
A better approach would be to use a wrapper library like PortAudio (http://www.portaudio.com/) which will make your code more portable and save you some of the boilerplate needed to get sound out of your program.
Try this (this program uses Z transform concept, a complete example that generates dtmf tones using ALSA and compilable on LINUX are available here)‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌:
/*
* Cosine Samples Generator
*
* Autor: Volnei Klehm
* Data: 04/01/2014
*/
#include <math.h>
#include <stdio.h>
#define S_FREQ 8000 /*Sample frequency, should be greater thar 2*sineFrequency
If using audio output it has to be the same saple frequency
Used there*/
const float frequency_in_Hertz = 697; /*set output frequency*/
const float generatorContant1 = cosf(2*M_PI*(frequency_in_Hertz/S_FREQ));
const float generatorContant2 = sinf(2*M_PI*(frequency_in_Hertz/S_FREQ));
float GenerateSignal(){
static float Register[2]={1,0};
static float FeedBack;
FeedBack=2*generatorContant1*Register[0]-Register[1];
Register[1]=Register[0];
Register[0]=FeedBack;
return (generatorContant2*Register[1]);
}
int main(void) {
/*generate 300 samples*/
for (int NumberOfSamples = 300; NumberOfSamples > 0; NumberOfSamples--)
printf("\n%f", GenerateSignal());
return 0;
}

How to implement readlink to find the path

Using the readlink function used as a solution to How do I find the location of the executable in C?, how would I get the path into a char array? Also, what do the variables buf and bufsize represent and how do I initialize them?
EDIT: I am trying to get the path of the currently running program, just like the question linked above. The answer to that question said to use readlink("proc/self/exe"). I do not know how to implement that into my program. I tried:
char buf[1024];
string var = readlink("/proc/self/exe", buf, bufsize);
This is obviously incorrect.
This Use the readlink() function properly for the correct uses of the readlink function.
If you have your path in a std::string, you could do something like this:
#include <unistd.h>
#include <limits.h>
std::string do_readlink(std::string const& path) {
char buff[PATH_MAX];
ssize_t len = ::readlink(path.c_str(), buff, sizeof(buff)-1);
if (len != -1) {
buff[len] = '\0';
return std::string(buff);
}
/* handle error condition */
}
If you're only after a fixed path:
std::string get_selfpath() {
char buff[PATH_MAX];
ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
if (len != -1) {
buff[len] = '\0';
return std::string(buff);
}
/* handle error condition */
}
To use it:
int main()
{
std::string selfpath = get_selfpath();
std::cout << selfpath << std::endl;
return 0;
}
Accepted answer is almost correct, except you can't rely on PATH_MAX because it is
not guaranteed to be defined per POSIX if the system does not have such
limit.
(From readlink(2) manpage)
Also, when it's defined it doesn't always represent the "true" limit. (See http://insanecoding.blogspot.fr/2007/11/pathmax-simply-isnt.html )
The readlink's manpage also give a way to do that on symlink :
Using a statically sized buffer might not provide enough room for the
symbolic link contents. The required size for the buffer can be
obtained from the stat.st_size value returned by a call to lstat(2) on
the link. However, the number of bytes written by readlink() and read‐
linkat() should be checked to make sure that the size of the symbolic
link did not increase between the calls.
However in the case of /proc/self/exe/ as for most of /proc files, stat.st_size would be 0. The only remaining solution I see is to resize buffer while it doesn't fit.
I suggest the use of vector<char> as follow for this purpose:
std::string get_selfpath()
{
std::vector<char> buf(400);
ssize_t len;
do
{
buf.resize(buf.size() + 100);
len = ::readlink("/proc/self/exe", &(buf[0]), buf.size());
} while (buf.size() == len);
if (len > 0)
{
buf[len] = '\0';
return (std::string(&(buf[0])));
}
/* handle error */
return "";
}
Let's look at what the manpage says:
readlink() places the contents of the symbolic link path in the buffer
buf, which has size bufsiz. readlink does not append a NUL character to
buf.
OK. Should be simple enough. Given your buffer of 1024 chars:
char buf[1024];
/* The manpage says it won't null terminate. Let's zero the buffer. */
memset(buf, 0, sizeof(buf));
/* Note we use sizeof(buf)-1 since we may need an extra char for NUL. */
if (readlink("/proc/self/exe", buf, sizeof(buf)-1) < 0)
{
/* There was an error... Perhaps the path does not exist
* or the buffer is not big enough. errno has the details. */
perror("readlink");
return -1;
}
char *
readlink_malloc (const char *filename)
{
int size = 100;
char *buffer = NULL;
while (1)
{
buffer = (char *) xrealloc (buffer, size);
int nchars = readlink (filename, buffer, size);
if (nchars < 0)
{
free (buffer);
return NULL;
}
if (nchars < size)
return buffer;
size *= 2;
}
}
Taken from: http://www.delorie.com/gnu/docs/glibc/libc_279.html
#include <stdlib.h>
#include <unistd.h>
static char *exename(void)
{
char *buf;
char *newbuf;
size_t cap;
ssize_t len;
buf = NULL;
for (cap = 64; cap <= 16384; cap *= 2) {
newbuf = realloc(buf, cap);
if (newbuf == NULL) {
break;
}
buf = newbuf;
len = readlink("/proc/self/exe", buf, cap);
if (len < 0) {
break;
}
if ((size_t)len < cap) {
buf[len] = 0;
return buf;
}
}
free(buf);
return NULL;
}
#include <stdio.h>
int main(void)
{
char *e = exename();
printf("%s\n", e ? e : "unknown");
free(e);
return 0;
}
This uses the traditional "when you don't know the right buffer size, reallocate increasing powers of two" trick. We assume that allocating less than 64 bytes for a pathname is not worth the effort. We also assume that an executable pathname as long as 16384 (2**14) bytes has to indicate some kind of anomaly in how the program was installed, and it's not useful to know the pathname as we'll soon encounter bigger problems to worry about.
There is no need to bother with constants like PATH_MAX. Reserving so much memory is overkill for almost all pathnames, and as noted in another answer, it's not guaranteed to be the actual upper limit anyway. For this application, we can pick a common-sense upper limit such as 16384. Even for applications with no common-sense upper limit, reallocating increasing powers of two is a good approach. You only need log n calls for a n-byte result, and the amount of memory capacity you waste is proportional to the length of the result. It also avoids race conditions where the length of the string changes between the realloc() and the readlink().