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

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

Related

not all PWMs are generated in Pi4 wiringPI language C

I am working on a project where I have to use multi-threading to generate multiple pwms. I am working on raspberry and I use WiringPI to generate softPWMs.
The problems is my raspberry does not want to generate 5 PWMs. Each time a run the code, the PWMs are generated randomly on 3 of the five pins I have setted. I do not know if it is the OS putting some threads on sleep or not.
I have no idea where the problem might be from. In fact, I tries using the same code to send periodically send many variable and it did work. But when I try using the same code with PWM it does not work. The code I am using is right below. If any of you has any idea please help
#include <wiringPi.h>
#include <stdio.h>
#include <softPwm.h>
#include <stdlib.h>
#include <pthread.h>
#define THREAD_NUM 1
struct thArg{
int PWM_pin1;
int rapportCyclique1;
int PWM_pin2;
int rapportCyclique2;
int PWM_pin3;
int rapportCyclique3;
int PWM_pin4;
int rapportCyclique4;
};
struct thArg data = {
22,20,
23,40,
24,80,
25,60
};
void* routine(void* args){
//int PWM_pin = *(int*)args->PWM_pin;
//int intensity = *(int*)args->rapportCyclique;
//pthread_mutex_lock(&mutexBuffer);
struct thArg *arrgs = (struct thArg *) args;
int PWM_pin1 = arrgs->PWM_pin1;
int rapportCyclique1 = arrgs->rapportCyclique1;
int PWM_pin2 = arrgs->PWM_pin2;
int rapportCyclique2 = arrgs->rapportCyclique2;
int PWM_pin3 = arrgs->PWM_pin3;
int rapportCyclique3 = arrgs->rapportCyclique3;
int PWM_pin4 = arrgs->PWM_pin4;
int rapportCyclique4 = arrgs->rapportCyclique4;
pinMode(PWM_pin1, OUTPUT);
softPwmCreate(PWM_pin1, 1, 100);
pinMode(PWM_pin2, OUTPUT);
softPwmCreate(PWM_pin1, 1, 100);
pinMode(PWM_pin3, OUTPUT);
softPwmCreate(PWM_pin1, 1, 100);
pinMode(PWM_pin4, OUTPUT);
softPwmCreate(PWM_pin1, 1, 100);
softPwmWrite(PWM_pin1, rapportCyclique1);
softPwmWrite(PWM_pin2, rapportCyclique2);
softPwmWrite(PWM_pin3, rapportCyclique3);
softPwmWrite(PWM_pin4, rapportCyclique4);
//pthread_mutex_unlock(&mutexBuffer);
}
void* routine(void*);
int main(int argc, char** argv)
{
wiringPiSetup();
pthread_t th[THREAD_NUM];
for(int i=0; i<THREAD_NUM; i++)
{
struct thArg *a = malloc(sizeof(struct thArg));
*a = data;
if(pthread_create(&th[i], NULL, &routine, a) != 0)
{
perror("failed to create thread\n");
exit( EXIT_FAILURE );
}
}
for(int i = 0; i<THREAD_NUM; i++){
if(pthread_join(th[i], NULL)!= 0)
{
perror("Failed to join thread\n");
exit( EXIT_FAILURE );
}
}
//pthread_mutex_destroy(&mutexBuffer);
return EXIT_SUCCESS;
}

Compile error for AI Thinker ESP32-CAM card

Hello I am a beginner of C language for microprocessors. I want to copy a .bmp file using copyimage() function .This error occurs when compile button is pushed:
#include "esp_camera.h"
#include "Arduino.h"
#include "FS.h" // SD Card ESP32
#include "SD_MMC.h" // SD Card ESP32
#include "soc/soc.h" // Disable brownour problems
#include "soc/rtc_cntl_reg.h" // Disable brownour problems
#include "driver/rtc_io.h"
#include <EEPROM.h> // read and write from flash memory
#include <SPI.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
// define the number of bytes you want to access
#define EEPROM_SIZE 1
// Pin definition for CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
int pictureNumber = 0;
int CopyNumber = 0;
void imgWriter(const char *imgName,
unsigned char *buf,
int len,
int width,
int height)// WRITE A FILE
{
fs::FS &fs = SD_MMC;
Serial.printf("Picture file name: %s\n",imgName);
Serial.printf("%d\n",len);
Serial.printf("%d\n",width);
Serial.printf("%d\n",height);
File fo =fs.open(imgName,FILE_WRITE);
if(!fo){
Serial.println("Failed to open file in writing mode");
}
else {
fo.write(buf,len); // payload (image), payload length
Serial.printf("Saved file to path: %s\n" , imgName);
EEPROM.write(0, pictureNumber);
EEPROM.commit();
}
fo.close();
}
void copyImage(const char *imgName,
int width,
int height,
const char *copyimage) // COPY A FILE
{
fs::FS &fs = SD_MMC; // Allows access to SD card
File fo =fs.open(imgName,FILE_READ);
File fy =fs.open(copyimage,FILE_WRITE);
if(!fo){
Serial.printf("Unable to open file for reading");
}
unsigned char header[54];
unsigned char colorTable[1024];
for(int i =0 ; i<54 ; i++){
header[i]= getc(fo); // ERROR IS HERE
}
int width1 = * ( int * )&header[18]; //Width information of the image
int height1 = * ( int * ) &header[22];
int bitDepth = * ( int * ) &header[28];
if(bitDepth <= 8 ){
fo.read(colorTable,1024);
}
fy.write(header,54);
unsigned char buf[(height1*width1)];
fo.read(buf,(height1 * width1));
if(bitDepth <= 8){
fy.write(colorTable,1024);
}
fy.write(buf,(height1*width1));
fy.close();
fo.close();
Serial.printf("SUCCESS");
EEPROM.commit();
}
void setup() {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
Serial.begin(115200);
//Serial.setDebugOutput(true);
//Serial.println();
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
if(psramFound()){
config.frame_size = FRAMESIZE_UXGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
// Init Camera
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
//Serial.println("Starting SD Card");
if(!SD_MMC.begin()){
Serial.println("SD Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD Card attached");
return;
}
camera_fb_t * fb = NULL;
// Take Picture with Camera
fb = esp_camera_fb_get();
if(!fb) {
Serial.println("Camera capture failed");
return;
}
// initialize EEPROM with predefined size
EEPROM.begin(EEPROM_SIZE);
pictureNumber = EEPROM.read(0) + 1;
CopyNumber = EEPROM.read(0) + 1;
// Path where new picture will be saved in SD Card
String path = "/picture" + String(pictureNumber) +".bmp"; // Dosyanın ismi
String copy_path = "/Copy" + String(CopyNumber) +".bmp";
imgWriter(path.c_str(),fb->buf,fb->len,fb->width,fb->height); // WRITE FUNCION CALL
copyImage(path.c_str(),fb->width,fb->height,copy_path.c_str()); // Copy
esp_camera_fb_return(fb);
// Turns off the ESP32-CAM white on-board LED (flash) connected to GPIO 4
pinMode(4, OUTPUT);
digitalWrite(4, LOW);
rtc_gpio_hold_en(GPIO_NUM_4);
delay(2000);
Serial.println("Going to sleep now");
delay(2000);
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
void loop() {
}
Error is : cannot convert 'fs::File' to 'FILE* {aka __sFILE*}' for argument '1' to 'int getc(FILE*)'
Contrary to the comments, your error is quite clear from the message and code:
You are trying to use a C library function getc with a ESP32 library object File.
That is impossible. getc can not work with this object, or any C++ object because it is a C function.
To read from the file object, you need to use its method read like this:
header[i] = fo.read();
You should read the library documentation for more information on how to use the File object, or see this tutorial on working with SD card:
https://diyi0t.com/sd-card-arduino-esp8266-esp32/

How to produce sound in C on Linux?

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

sending various scsi commands through a single function

I have been playing around with scsi command and I can send some basic commands like different inquirys and such.
I have been using this example to to generate my inquiry. I am working on making this example work with different scsi commands.
http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/pexample.html
I have changed to function to accept different scsi commands through a struct and it also returns a struct based on the output. This works with an inquiry flawlessly. However if I send a READ CAPACITY(16) command the function triggers on the if statement:
(io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK)
I am new to scsi programming so I might be doing something totally wrong...
my READ CAPACITY(16) command is just this:
scsi_read_capacity.cmdblk[0]=0x9e;
scsi_read_capacity.cmdblk[13]=32;
the rest of the CDB are 0!
here is the code:
#include <stdio.h>
#include <sys/ioctl.h>
#include <scsi/sg.h>
/* global struct to store return data from a scsi cmd*/
typedef struct SCSI_data {
unsigned char data[1024];
unsigned char raw_sens[252];
unsigned char sense_key;
unsigned char additional_sense_code;
unsigned char additional_sense_qualifier;
unsigned char additional_sense_length;
unsigned char sense_data_descriptors[10][244];
int result;
} SCSI_data;
/* global struct to store return data from a scsi cmd*/
typedef struct SCSI_cmd {
int sg_fd;
unsigned char cmdblk[32];
int cmdblklength;
int allocation_length;
int xfer;
int timeout;
} SCSI_cmd;
SCSI_data send_scsicmd(SCSI_cmd cmdobject) {
int k;;
unsigned char inqBuff[cmdobject.allocation_length];
unsigned char sense_buffer[252];
SCSI_data output_data;
sg_io_hdr_t io_hdr;
/* Prepare INQUIRY command */
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
io_hdr.interface_id = 'S';
io_hdr.cmd_len = cmdobject.cmdblklength;
io_hdr.mx_sb_len = sizeof(sense_buffer);
io_hdr.dxfer_direction = cmdobject.xfer;
io_hdr.dxfer_len = cmdobject.allocation_length;
io_hdr.dxferp = inqBuff;
io_hdr.cmdp = cmdobject.cmdblk;
io_hdr.sbp = sense_buffer;
io_hdr.timeout = cmdobject.timeout;
if (ioctl(cmdobject.sg_fd, SG_IO, &io_hdr) < 0) {
output_data.result=2;
return output_data;
}
/* now for the error processing */
if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
output_data.result=1;
if (io_hdr.sb_len_wr > 0) {
printf("INQUIRY sense data: ");
for (k = 0; k < io_hdr.sb_len_wr; ++k) {
if ((k > 0) && (0 == (k % 10)))
printf("\n ");
printf("0x%02x ", sense_buffer[k]);
}
printf("\n");
}
if (io_hdr.masked_status)
printf("INQUIRY SCSI status=0x%x\n", io_hdr.status);
if (io_hdr.host_status)
printf("INQUIRY host_status=0x%x\n", io_hdr.host_status);
if (io_hdr.driver_status)
printf("INQUIRY driver_status=0x%x\n", io_hdr.driver_status);
}
else { /* assume INQUIRY response is present */
output_data.result=0;
for (k=0;k<cmdobject.allocation_length;k++) {
output_data.data[k]=inqBuff[k];
}
}
return output_data;
}
int main(int argc, char * argv[]) {
FILE *driveptr=fopen(argv[1], "r");
int i;
SCSI_data scsi_data_read_capacity;
SCSI_cmd scsi_read_capacity;
scsi_read_capacity.sg_fd=fileno(driveptr);
scsi_read_capacity.cmdblk[0]=0x9e;
scsi_read_capacity.cmdblk[13]=32;
scsi_read_capacity.cmdblklength=16;
scsi_read_capacity.xfer=SG_DXFER_FROM_DEV;
scsi_read_capacity.allocation_length=32;
scsi_read_capacity.timeout=1000;
scsi_data_read_capacity=send_scsicmd(scsi_read_capacity);
if (scsi_data_read_capacity.result==0) {
printf(" capacity in blocks: %02x%02x%02x%02x%02x%02x%02x%02x\n",
scsi_data_read_capacity.data[0],
scsi_data_read_capacity.data[1],
scsi_data_read_capacity.data[2],
scsi_data_read_capacity.data[3],
scsi_data_read_capacity.data[4],
scsi_data_read_capacity.data[5],
scsi_data_read_capacity.data[6],
scsi_data_read_capacity.data[7]);
printf(" blocksize: %02x%02x%02x%02x\n",
scsi_data_read_capacity.data[8],
scsi_data_read_capacity.data[9],
scsi_data_read_capacity.data[10],
scsi_data_read_capacity.data[11]);
}
fclose(driveptr);
return 0;
}
I had just a small problem. My CDB was wrong!
I had to use this:
scsi_read_capacity.cmdblk[0]=0x9E;
scsi_read_capacity.cmdblk[1]=0x10;
scsi_read_capacity.cmdblk[13]=32;
the second byte had to be equal to 0x10, this is because the scsi cmd 0x9E is a service action command which accepts an argument in the second byte which defines its behavior!

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