How to produce sound in C on Linux? - c

I need a way to play certain musical notes in my C program on Linux.
When using windows, it is possible to #include <dos.h> and use straight forward functions like sound(note/frequency), delay(time in ms), and the self explaining nosound().
Is there anything parallel on Linux?
Thanks

I like the tip above concerning libao - I just gave it a try and it works nicely. Here is a similar level of complexity using OpenAL to synthesize a raw audio buffer in PCM format then to render as audio
// sudo apt-get install libopenal-dev
// gcc -o openal_play_monday openal_play_monday.c -lopenal -lm
#include <stdio.h>
#include <stdlib.h> // gives malloc
#include <math.h>
#ifdef __APPLE__
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#elif __linux
#include <AL/al.h>
#include <AL/alc.h>
#include <unistd.h>
#endif
ALCdevice * openal_output_device;
ALCcontext * openal_output_context;
ALuint internal_buffer;
ALuint streaming_source[1];
int al_check_error(const char * given_label) {
ALenum al_error;
al_error = alGetError();
if(AL_NO_ERROR != al_error) {
printf("ERROR - %s (%s)\n", alGetString(al_error), given_label);
return al_error;
}
return 0;
}
void MM_init_al() {
const char * defname = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
openal_output_device = alcOpenDevice(defname);
openal_output_context = alcCreateContext(openal_output_device, NULL);
alcMakeContextCurrent(openal_output_context);
// setup buffer and source
alGenBuffers(1, & internal_buffer);
al_check_error("failed call to alGenBuffers");
}
void MM_exit_al() {
ALenum errorCode = 0;
// Stop the sources
alSourceStopv(1, & streaming_source[0]); // streaming_source
int ii;
for (ii = 0; ii < 1; ++ii) {
alSourcei(streaming_source[ii], AL_BUFFER, 0);
}
// Clean-up
alDeleteSources(1, &streaming_source[0]);
alDeleteBuffers(16, &streaming_source[0]);
errorCode = alGetError();
alcMakeContextCurrent(NULL);
errorCode = alGetError();
alcDestroyContext(openal_output_context);
alcCloseDevice(openal_output_device);
}
void MM_render_one_buffer() {
/* Fill buffer with Sine-Wave */
// float freq = 440.f;
float freq = 100.f;
float incr_freq = 0.1f;
int seconds = 4;
// unsigned sample_rate = 22050;
unsigned sample_rate = 44100;
double my_pi = 3.14159;
size_t buf_size = seconds * sample_rate;
// allocate PCM audio buffer
short * samples = malloc(sizeof(short) * buf_size);
printf("\nhere is freq %f\n", freq);
int i=0;
for(; i<buf_size; ++i) {
samples[i] = 32760 * sin( (2.f * my_pi * freq)/sample_rate * i );
freq += incr_freq; // change freq just to make things interesting
if (100.0 > freq || freq > 5000.0) {
incr_freq *= -1.0f; // toggle direction of freq increment
}
}
/* upload buffer to OpenAL */
alBufferData( internal_buffer, AL_FORMAT_MONO16, samples, buf_size, sample_rate);
al_check_error("populating alBufferData");
free(samples);
/* Set-up sound source and play buffer */
// ALuint src = 0;
// alGenSources(1, &src);
// alSourcei(src, AL_BUFFER, internal_buffer);
alGenSources(1, & streaming_source[0]);
alSourcei(streaming_source[0], AL_BUFFER, internal_buffer);
// alSourcePlay(src);
alSourcePlay(streaming_source[0]);
// ---------------------
ALenum current_playing_state;
alGetSourcei(streaming_source[0], AL_SOURCE_STATE, & current_playing_state);
al_check_error("alGetSourcei AL_SOURCE_STATE");
while (AL_PLAYING == current_playing_state) {
printf("still playing ... so sleep\n");
sleep(1); // should use a thread sleep NOT sleep() for a more responsive finish
alGetSourcei(streaming_source[0], AL_SOURCE_STATE, & current_playing_state);
al_check_error("alGetSourcei AL_SOURCE_STATE");
}
printf("end of playing\n");
/* Dealloc OpenAL */
MM_exit_al();
} // MM_render_one_buffer
int main() {
MM_init_al();
MM_render_one_buffer();
}
If you want to take OpenAL further ... take a gander at this
https://github.com/scottstensland/render-audio-openal
Out of the box OpenAL plays a buffer of PCM audio just fine ... however it leaves as an exercise the ability to play a stream. In that github repo I wrote an audio server using OpenAL which implements playing streaming audio ... enjoy

Windows uses its own one and only sound architecture, therefore you can access the sound() routine.
Different linux machines, depending on the packages installed, may require different approaches.
Maybe the utility beep (out of this question on stackexchange) can guide you to the right direction

one way
including
#include<conio.h>
and in side main() or where you want to use call print("\a")
printf("\a");
2nd way
including header file
#include <windows.h>
and calling function
Beep(500, 500);
Beep(freq, dur); where freq =beep frequency which is int and dutation in also int

Related

Problems using OpenCV with ZBar in C

I'm trying to use OpenCV to load a jpg image from file and pass it to zbar library to decode a barcode. However, no barcodes are decoded properly, even though the code below works when I use functions from libpng to load the image. I have no errors, and I have no idea where the problem is, as I have already checked all posts I could find and nothing worked.
Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
#include <zbar.h>
#include <cv.h>
#include <highgui.h>
#include <math.h>
zbar_image_scanner_t *scanner = NULL;
IplImage* cvLoadImage(const char* filename, int iscolor);
int main (int argc, char **argv)
{
// create a reader
scanner = zbar_image_scanner_create();
// configure the reader
zbar_image_scanner_set_config(scanner, 0, ZBAR_CFG_ENABLE, 1);
// obtain image data with opencv
IplImage* img = 0;
int height,width,step,channels;
img = cvLoadImage(argv[1], 1);
height = img->height;
width = img->width;
step = img->widthStep;
channels = img->nChannels;
void *raw = (void *)(img->imageData);
printf("Processing a %dx%d image \n",height,width);
// wrap image data
zbar_image_t *image = zbar_image_create();
zbar_image_set_format(image, *(int*)"Y800");
zbar_image_set_size(image, width, height);
zbar_image_set_data(image, raw, width * height, zbar_image_free_data);
// scan the image for barcodes
int n = zbar_scan_image(scanner, image);
if (n==0){
printf("No barcode detected for image %s\n", argv[1]);
return 1;
}
// extract results
if (n!=0) {
const zbar_symbol_t *symbol = zbar_image_first_symbol(image);
printf("symbol extracted \n");
for(; symbol; symbol = zbar_symbol_next(symbol)) {
// do something useful with results
zbar_symbol_type_t typ = zbar_symbol_get_type(symbol);
const char *dataZ = zbar_symbol_get_data(symbol);
printf("decoded %s symbol \"%s\" of image %s \n", zbar_get_symbol_name(typ), dataZ, argv[1]);
}
}
// clean up
zbar_image_destroy(image);
zbar_image_scanner_destroy(scanner);
return 0;
}
That code worked perfectly for me. I used it in my program with small changes:
I don't show how I get the 'struct _IplImage *' {aka 'IplImage *'} because it is done in another file, and get it as param, but it is of course done with cvLoadImage().
I used "GREY" instead of "Y800", but I tried "Y800" and also worked, as they are fundamentally the same.
This works (at least with openCV 2.4.9; openCV is deprecating its C API, and its C++ API should be used instead (I'm against this, but nothing can be done :( )):
/******************************************************************************
******* headers **************************************************************
******************************************************************************/
/* Standard C ----------------------------------------------------------------*/
/* snprintf() */
#include <stdio.h>
/* Packages ------------------------------------------------------------------*/
/* opencv */
#include <cv.h>
/* zbar */
#include <zbar.h>
/* Module --------------------------------------------------------------------*/
#include "this_file.h"
/******************************************************************************
******* macros ***************************************************************
******************************************************************************/
# define ZB_CODES_MAX (10)
# define ZBAR_LEN_MAX (1048576)
/******************************************************************************
******* structs **************************************************************
******************************************************************************/
struct ZB_Codes {
int n;
struct {
int type;
char sym_name [80];
char data [ZBAR_LEN_MAX];
} arr [ZB_CODES_MAX];
};
/******************************************************************************
******* variables ************************************************************
******************************************************************************/
struct ZB_Codes zb_codes;
/******************************************************************************
******* functions ************************************************************
******************************************************************************/
void img_zb_decode (struct _IplImage *imgptr)
{
struct zbar_image_scanner_s *scanner;
struct zbar_image_s *image_zb;
const struct zbar_symbol_s *symbol;
/* Type of code to scan */
/* 0 for all; set to another if used only for a specific barcode */
int code_type;
code_type = 0;
/* create & configure a reader */
scanner = zbar_image_scanner_create();
zbar_image_scanner_set_config(scanner, code_type, ZBAR_CFG_ENABLE, 1);
/* wrap image data */
image_zb = zbar_image_create();
zbar_image_set_format(image_zb, *(int *)"GREY");
zbar_image_set_size(image_zb, imgptr->width, imgptr->height);
zbar_image_set_data(image_zb, (void *)(imgptr->imageData),
(imgptr->width * imgptr->height), NULL);
/* scan the image for barcodes */
int i;
zb_codes.n = zbar_scan_image(scanner, image_zb);
if (zb_codes.n) {
/* extract results */
symbol = zbar_image_first_symbol(image_zb);
for (i = 0; i < ZB_CODES_MAX && symbol; i++) {
/* Write results into array */
zb_codes.arr[i].type = zbar_symbol_get_type(symbol);
snprintf(zb_codes.arr[i].sym_name, 80, "%s",
zbar_get_symbol_name(
zb_codes.arr[i].type));
snprintf(zb_codes.arr[i].data, ZBAR_LEN_MAX, "%s",
zbar_symbol_get_data(symbol));
/* Load next symbol */
symbol = zbar_symbol_next(symbol);
}
}
/* clean up */
zbar_image_destroy(image_zb);
zbar_image_scanner_destroy(scanner);
}
/******************************************************************************
******* end of file **********************************************************
******************************************************************************/

Getting volume value from pulseaudio

I've written this code by looking at various examples: Python pulseaudio monitor, Pavumeter source, async playback example, and Pacat source.
I have successfully connected to a sink and am able to record it, but my problem is, I'm stuck at getting the volume value out. If I try printing value from the read function, I just get a bunch of random numbers at a second's interval.
Now I'm not asking for someone to finish writing the code for me, I'd just like some tips, help so that I could head towards the right direction. How do I retrieve the volume value?
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <pulse/pulseaudio.h>
static int latency = 20000; // start latency in micro seconds
static int sampleoffs = 0;
static short sampledata[300000];
static pa_buffer_attr bufattr;
static int underflows = 0;
static pa_sample_spec ss;
// This callback gets called when our context changes state. We really only
// care about when it's ready or if it has failed
void pa_state_cb(pa_context *c, void *userdata) {
pa_context_state_t state;
int *pa_ready = userdata;
state = pa_context_get_state(c);
switch (state) {
// These are just here for reference
case PA_CONTEXT_UNCONNECTED:
case PA_CONTEXT_CONNECTING:
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
default:
break;
case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED:
*pa_ready = 2;
break;
case PA_CONTEXT_READY:
*pa_ready = 1;
break;
}
}
static void stream_read_cb(pa_stream *s, size_t length, void *userdata) {
const void *data;
pa_stream_peek(s, &data, &length);
data = (const unsigned char*) data;
printf("%u", data);
pa_stream_drop(s);
}
int main(int argc, char *argv[]) {
pa_mainloop *pa_ml;
pa_mainloop_api *pa_mlapi;
pa_context *pa_ctx;
pa_stream *recordstream;
int r;
int pa_ready = 0;
int retval = 0;
unsigned int a;
double amp;
int test = 0;
// Create a mainloop API and connection to the default server
pa_ml = pa_mainloop_new();
pa_mlapi = pa_mainloop_get_api(pa_ml);
pa_ctx = pa_context_new(pa_mlapi, "Simple PA test application");
pa_context_connect(pa_ctx, NULL, 0, NULL);
// This function defines a callback so the server will tell us it's state.
// Our callback will wait for the state to be ready. The callback will
// modify the variable to 1 so we know when we have a connection and it's
// ready.
// If there's an error, the callback will set pa_ready to 2
pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready);
// We can't do anything until PA is ready, so just iterate the mainloop
// and continue
while (pa_ready == 0) {
pa_mainloop_iterate(pa_ml, 1, NULL);
}
if (pa_ready == 2) {
retval = -1;
goto exit;
}
ss.rate = 44100;
ss.channels = 2;
ss.format = PA_SAMPLE_U8;
recordstream = pa_stream_new(pa_ctx, "Record", &ss, NULL);
if (!recordstream) {
printf("pa_stream_new failed\n");
}
pa_stream_set_read_callback(recordstream, stream_read_cb, NULL);
r = pa_stream_connect_record(recordstream, NULL, NULL, PA_STREAM_PEAK_DETECT);
if (r < 0) {
printf("pa_stream_connect_playback failed\n");
retval = -1;
goto exit;
}
// Run the mainloop until pa_mainloop_quit() is called
// (this example never calls it, so the mainloop runs forever).
// printf("%s", "Running Loop");
pa_mainloop_run(pa_ml, NULL);
exit:
// clean up and disconnect
pa_context_disconnect(pa_ctx);
pa_context_unref(pa_ctx);
pa_mainloop_free(pa_ml);
return retval;
}
Looking at the original question from UNIX.StackExchange, it looks like you're trying to create a VU meter. It can be done using an envelope detector. You have to read the input values and then average their rectified value. A simple envelope detector can be done as an exponential moving average filter.
float level = 0; // Init time
const float alpha = COEFFICIENT; // See below
...
// Inside sample loop
float input_signal = fabsf(get_current_sample());
level = level + alpha * (input_signal - level);
Here, alpha is the filter coefficient, which can be calculated as:
const float alpha = 1.0 - expf( (-2.0 * M_PI) / (TC * SAMPLE_RATE) );
Where TC is known as the "time constant" parameter, measured in seconds, which defines how fast you want to "follow" the signal. Setting it too short makes the VU meter very "bumpy" and setting it too long will miss transients in the signal. 10 mS is a good value to start from.

PaStreamCallbackTimeInfo members are all 0

From the PortAudio docs:
Stream Timing Information
When using the callback I/O method your stream callback function
receives timing information via a pointer to a
PaStreamCallbackTimeInfo structure. This structure contains the
current time along with the estimated hardware capture and playback
time of the first sample of the input and output buffers. All times
are measured in seconds relative to a Stream-specific clock. The
current Stream clock time can be retrieved using Pa_GetStreamTime().
So PaStreamCallbackTimeInfo::currentTime somehow indicates the current time and PaStreamCallbackTimeInfo::outputBufferDacTime should indicate the output time of the first sample in the current buffer. I don't know why but, on Linux, these values are all zero for me. Maybe I'm doing something wrong. Here's the code and the output:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include "portaudio.h"
#define PI 3.14159265359
#define SRATE 44100
#define FREQ 440
#define DURATION 5000
int
audio_callback(
const void* inbuf,
void* outbuf,
unsigned long bufsize,
const PaStreamCallbackTimeInfo* time_info,
PaStreamCallbackFlags status_flags,
void* user_data)
{
(void)inbuf;
(void)status_flags;
double* phase = (double*)user_data;
float* out = (float*)outbuf;
printf(
"current time = %f; out time = %f\n",
time_info->currentTime,
time_info->outputBufferDacTime);
for (unsigned long i = 0; i < bufsize; i++)
{
*phase += 2 * PI * FREQ / SRATE;
out[i] = sin(*phase);
}
return 0;
}
int
main(int argc, char** argv)
{
(void)argc;
(void)argv;
PaError pa_error;
PaStream* stream = NULL;
int error = 0;
double phase = 0;
pa_error = Pa_Initialize();
if (pa_error != paNoError)
{
return 1;
}
pa_error = Pa_OpenDefaultStream(
&stream,
0,
1,
paFloat32,
SRATE,
paFramesPerBufferUnspecified,
&audio_callback,
&phase);
if (pa_error != paNoError)
{
error = 1;
goto exit;
}
pa_error = Pa_StartStream(stream);
if (pa_error != paNoError)
{
error = 1;
goto exit;
}
Pa_Sleep(DURATION);
pa_error = Pa_CloseStream(stream);
if (pa_error != paNoError)
{
error = 1;
goto exit;
}
printf("Done.\n");
exit:
Pa_Terminate();
if (pa_error != paNoError)
{
printf("PortAudio error: %s\n", Pa_GetErrorText(pa_error));
}
return error;
}
Output:
current time = 0.000000; out time = 0.000000
current time = 0.000000; out time = 0.000000
current time = 0.000000; out time = 0.000000
current time = 0.000000; out time = 0.000000
...
Addendum: This same piece of code seems to work fine with Visual Studio in Windows 10.
Your example compiles fine on my Mac and returns meaningful time information so the issue is not in your code.
You haven't said which audio backend you're using on Linux, but if you're using ALSA and PulseAudio, there've been problems getting time info with those (see there for instance). In this specific case of ALSA/PulseAudio, Pulse is the one to blame and PortAudio has nothing to do with that.
If you're using a different audio backend, you might want to check the implementation of the GetStreamTime() function in the corresponding src/hostapi/<your_backend> PortAudio source folder.
As a side note, never make I/O operations in an audio callback in a real product. printf is a huge function which takes quite a lot of time to execute (from an audio callback point-of-view).

I can not understand how to use buffers in the audio resampling

What i have tryed:
Player.c
const int BITS=8;
int isPaused=0;
static mpg123_handle *mh;
static unsigned char *buffer;
static size_t buffer_size;
static size_t done;
char * resBuffer;
//from global stat!
int outfreq=22050; int infreq=44100;
int resetMp3(char * song)
{
int err;
int channels, encoding;
long rate;
/* Inizialize */
mpg123_init();
mh = mpg123_new(NULL, &err);
buffer_size = mpg123_outblock(mh);
buffer = (unsigned char*) malloc(buffer_size * sizeof(unsigned char));
resBuffer=(unsigned char*) malloc(buffer_size * sizeof(unsigned char) * (1.0+(outfreq/infreq)));
/* open the file and get the decoding format */
mpg123_open(mh,song);
mpg123_getformat(mh, &rate, &channels, &encoding);
/* set the output format and open the output device */
int bits=(mpg123_encsize(encoding) * BITS);
initAudioDev(bits,rate,channels);
//Add for resampling
inizializeResample(infreq,outfreq);
}
int playMp3(){
/* decode and play */
if (isPaused==0 && mpg123_read(mh, buffer, buffer_size, &done) == MPG123_OK)
{
//char * resBuffer=malloc(sizeof(unsigned char)*buffer_size/(outfreq/infreq));
resBuffer=&buffer[0];
resample(buffer,resBuffer,done);
writeAudio((char*)resBuffer,done);
} else {
if (isPaused==0) return 2;
}
return 0;
}
int freeMp3()
{
free(buffer);
mpg123_close(mh);
mpg123_delete(mh);
mpg123_exit();
freeAudioDev();
endResample();
}
void setMp3Status(int value)
{
if(value==0||value==1)
{
isPaused=value;
} else {
isPaused=!isPaused;
}
}
Resampling.c
#include <assert.h>
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include "libavcodec/avcodec.h"
#define LENGTH_MS 1000 // how many milliseconds of speech to store
#define RATE 44100 // the sampling rate (input)
struct AVResampleContext* audio_cntx = 0;
int samples_consumed;
void inizializeResample(int inRate, int outRate)
{
//char out_buffer[ sizeof( in_buffer ) * 4];
audio_cntx = av_resample_init( outRate, //out rate
inRate, //in rate
4, //filter length 16
3, //phase count 10
0, //linear FIR filter
0.6 ); //cutoff frequency
assert( audio_cntx && "Failed to create resampling context!");
}
void resample(char dataIn[],char dataOut[],int nsamples)
{
int samples_output = av_resample( audio_cntx, //resample context
(short*)dataOut, //buffout
(short*)dataIn, //buffin
&samples_consumed, //&consumed
nsamples, //nb_samples
(sizeof(dataOut)*nsamples),//lenout sizeof(out_buffer)/2
0);//is_last
assert( samples_output > 0 && "Error calling av_resample()!" );
}
void endResample()
{
av_resample_close( audio_cntx );
}
Now, when I execute this code, the audio isn't clear and resampling isn't done, problably because have wrong something with pointers and buffers.I review this code hundreds of time without find the error.
Can help me to find it and explain right how i should correctly size the buffers?
Now i think another problem is that i can't define what mpg123_read give me, if you explain this i love you.
Library used:Libmpg123 - The decoder function: mpg123_read
Resampling Library: FFMpeg AVCodec Library.
Ps: yes problaby a noob question, but after many attempts, StackOverflow is the only thing that can help me, THANK YOU

audio delay making it work

I am trying to implement a simple audio delay in C.
i previously made a test delay program which operated on a printed sinewave and worked effectively.
I tried incorporating my delay as the process in the SFProcess - libsndfile- replacing the sinewave inputs with my audio 'data' input.
I nearly have it but instead of a clean sample delay I am getting all sorts of glitching and distortion.
Any ideas on how to correct this?
#include <stdio.h>
#include </usr/local/include/sndfile.h>//libsamplerate libsamplerate
//#include </usr/local/include/samplerate.h>
#define BUFFER_LEN 1024 //defines buffer length
#define MAX_CHANNELS 2 //defines max channels
static void process_data (double *data, double*circular,int count, int numchannels, int circular_pointer );
enum {DT_PROGNAME,ARG_INFILE,ARG_OUTFILE,ARG_NARGS, DT_VOL};
int main (int argc, const char * argv[])//Main
{
static double data [BUFFER_LEN]; // the buffer that carries the samples
double circular [44100] = {0}; // the circular buffer for the delay
for (int i = 0; i < 44100; i++) { circular[i] = 0; } // zero the circular buffer
int circular_pointer = 0; // where we currently are in the circular buffer
//float myvolume; // the volume entered by the user as optional 3rd argument
SNDFILE *infile, *outfile;
SF_INFO sfinfo;
int readcount;
const char *infilename = NULL;
const char *outfilename = NULL;
if(argc < ARG_NARGS) {
printf("usage: %s infile outfile\n",argv[DT_PROGNAME]);
return 1;
}
//if(argc > ARG_NARGS) {
//
// myvolume = argv[DT_VOL];
//};
infilename = argv[ARG_INFILE];
outfilename = argv[ARG_OUTFILE];
if (! (infile = sf_open (infilename, SFM_READ, &sfinfo)))
{printf ("Not able to open input file %s.\n", infilename) ;
puts (sf_strerror (NULL)) ;
return 1 ;
};
if (! (outfile = sf_open (outfilename, SFM_WRITE, &sfinfo)))
{ printf ("Not able to open output file %s.\n", outfilename) ;
puts (sf_strerror (NULL)) ;
return 1 ;
} ;
while ((readcount = sf_read_double (infile, data, BUFFER_LEN)))
{ process_data (data, circular, readcount, sfinfo.channels, circular_pointer) ;
sf_write_double (outfile, data, readcount) ;
};
sf_close (infile) ;
sf_close (outfile) ;
printf("the sample rate is %d\n", sfinfo.samplerate);
return 0;
}
static void process_data (double *data, double *circular, int count, int numchannels, int circular_pointer) {
//int j,k;
//float vol = 1;
int playhead;
int wraparound = 10000;
float delay = 1000; // delay time in samples
for (int ind = 0; ind < BUFFER_LEN; ind++){
circular_pointer = fmod(ind,wraparound); // wrap around pointer
circular[circular_pointer] = data[ind];
playhead = fmod(ind-delay, wraparound); // read the delayed signal
data[ind] = circular[playhead]; // output delayed signal
circular[ind] = data[ind]; // write the incoming signal
};
//volume
/*for (j=0; j<numchannels; j++) {
for (k=0; k<count; k++){
data[k] = data[k]*-vol;*/
//}printf ("the volume is %f", vol);
return;
}
There are a few issues with your code that are causing you to access out of your array bounds and to not read\write your circular buffer in the way intended.
I would suggest reading http://en.wikipedia.org/wiki/Circular_buffer to get a better understanding of circular buffers.
The main issues your code is suffering:
circular_pointer should be initialised to the delay amount (essentially the write head is starting at 0 so there is never any delay!)
playhead and circular_buffer are not updated between calls to process_data (circular_buffer is passed by value...)
playhead is reading from negative indices. The correct playhead calculation is
#define MAX_DELAY 44100
playhead++;
playhead = playhead%MAX_DELAY;
The second write to circular_buffer at the end of process_data is unnecessary and incorrect.
I would strongly suggest spending some time running your code in a debugger and closely watching what your playhead and circular_pointer are doing.
Mike
At least one problem is that you pass circular_pointer by value, not by reference. When you update it in the function, it's back to the same value next time you call the function.
I think you are on the right track, here, but if you want something that's structured a bit better, you might also want to checkout this answer:
how to add echo effect on audio file using objective-c
delay in sample can be put as 100 ms would be sufficient

Resources