Counting into an array and writing to text file xcode - c

Hi I am trying to count in note data from keyboard and write the data to a text file which will subsequently be read out of and played back as notes.
I seem to only be able to write one line of numbers to the text file and help would be most appreciated. Sorry i still have some of my function code included in the global.
#define SEQ_NOTENUM 8
#define SEQ_NUM 2
// structures //
typedef struct
{
int notenumber;
int velocity;
}NoteData;
typedef struct
{
float frequency;
float amplitude;
} OscData;
// functions //
float mtof(int note);
// originally in main //
OscData noteToOsc(NoteData note);
int setcount, count;
int currentset;
OscData osc;
int main()
{
int key, vel;
NoteData sequence[SEQ_NUM][SEQ_NOTENUM];
OscData noteToOsc(NoteData note);
FILE* Sequence1;
// START PROGRAM RECORD -- WRITE an IF/ELSE to run program -
dummy line atm//
aserveGetVelocity();
Sequence1 = fopen ("sequence1.txt", "w");
if (Sequence1 == NULL)
{
printf("file Error\n");
}
else
{
for(setcount = 0; setcount < SEQ_NUM; setcount++)
{
printf("--- Please enter sequence %d (%d notes)...\n",
setcount, SEQ_NUM);
count = 0;
while(count < SEQ_NOTENUM)
{
key = aserveGetNote();
vel = aserveGetVelocity();
if(vel > 0)
{
sequence[setcount][count].notenumber = key;
sequence[setcount][count].velocity = vel;
fprintf(Sequence1, "note %d - %d/%d\n", count, key,
vel);
count++;
}
fclose(Sequence1);
}
return 0;
}
}

The code's indentation is messed up, obscuring the fact that fclose(Sequence1) is closing the file after only one pass through the inner loop. You probably want to move that to somewhere further down.

Related

String in structure gets deleted

I'm working on the last exercise of the "Think like a computer scientist, C version" book and I have some trouble with one particular point.
The exercise consists of making a small game, where the computer picks a random value between 0 and 20 and then asks me to guess the number.
After that, the computer counts the number of tries I made and, if I get a better score than the previous party, I need to store my name and the number of tries in a structure.
My problem is the following: When I restart the game, the string value, player_name, in the structure gets somehow deleted but player_score is still there.
First, I made a "call by value" function to create the structure and then a tried with a "call by reference" but getting the same results.
I think I tried everything I could with my actual knowledge for now; so, if someone could check my code and give me some tips about what's wrong I would much appreciate it!
//HEADERS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define FALSE 0
#define TRUE 1
//TYPEDEF STRUCTS
typedef struct
{
int player_score;
char *player_name;
} HS_Player;
//FUNCTION PROTOTYPES
int Random_Value(void);
int Get_User_Choice(void);
int Check_Result(int computer, int my_choice);
int Try_Again(int game_result, int computer);
void Player_Infos(HS_Player *player_p, int score);
int Game_Restart(void);
//MAIN
int main(void)
{
int end_game;
int high_score_value = 100;
HS_Player player;
while (end_game != TRUE)
{
int computer_number = Random_Value();
printf("Guess the number between 0 et 20 chosen by the computer.\n");
int your_number = Get_User_Choice();
int result_game = Check_Result(computer_number, your_number);
int tries_to_win = Try_Again(result_game, computer_number);
printf("Number of tries: %i\n", tries_to_win);
if (tries_to_win < high_score_value)
{
Player_Infos(&player, tries_to_win );
high_score_value = player.player_score;
}
printf("Highest score: %i By: %s\n", player.player_score, player.player_name);
printf("\n");
end_game = Game_Restart();
}
return EXIT_SUCCESS;
}
//Random_Value FUNCTION
int Random_Value(void)
{
srand(time(NULL));
int x = rand();
int y = x % 20;
return y;
}
//Get_User_Choice FUNCTION
int Get_User_Choice(void)
{
int success, x;
char ch;
printf("Your Guess:\t");
success = scanf("%i", &x);
while (success != 1)
{
printf("Your input is not a number. Please try again:\t");
while ((ch = getchar()) != '\n' && ch != EOF);
success = scanf("%i", &x);
}
if (x < 0 || x > 20)
{
printf("Your input must be between 0 and 20. Please try again.\n");
Get_User_Choice();
}
return x;
}
//Check_Result FUNCTION
int Check_Result(int computer, int my_choice)
{
int check_result;
if (my_choice < computer)
{
printf("Computer number is larger!\n");
check_result = FALSE;
}
else if (my_choice > computer)
{
printf("Computer number is smaller!\n");
check_result = FALSE;
}
else if (my_choice == computer)
{
printf("It's a Match! You chose the same number than the computer.\n");
printf("\n");
check_result = TRUE;
}
return check_result;
}
//Try_Again FUNCTION
int Try_Again(int game_result, int computer)
{
int tries_befor_success = 1;
while (game_result != TRUE)
{
int your_number = Get_User_Choice();
game_result = Check_Result(computer, your_number);
tries_befor_success++;
}
return tries_befor_success;
}
//Player_Infos FUNCTION
void Player_Infos(HS_Player *player_p, int score)
{
char new_name[80];
printf("Congrats! Your made a new high score.\n");
printf("What's your name ?\t");
scanf("%s", new_name);
printf("\n");
player_p->player_score = score;
player_p->player_name = new_name;
}
//Game_Restart FUNCTION
int Game_Restart(void)
{
int quit_value;
printf("Quit Game ?\n");
printf("Press 'y' to quit or any other keys to continue.\n");
fflush(stdin);
char quit_game = getchar();
printf("\n");
if (quit_game == 'y')
{
quit_value = TRUE;
}
else
{
quit_value = FALSE;
}
return quit_value;
}
The problem is that, in your Player_Infos function, you are assigning the address of a local array to the char* player_name pointer member of the passed structure. When that function ends, the local array it used will be deleted and the pointer in the structure will be invalid. (In the case of the player_score, you don't have that problem, because the given value is copied to the structure member.)
There are several ways around this; one would be to use the strdup() function to make a copy of the local char new_name[80]; array – but that is really overkill, and you would need to manage (i.e. free()) that allocated string whenever you make a modification.
A simpler way is to make the player_name member an actual array of char and then use strcpy() to copy the local array into that member.
Better, still, with the player_name member defined as char [80], you can read directly into that (in the function), and avoid the local array completely:
typedef struct
{
int player_score;
char player_name[80];
} HS_Player;
//...
void Player_Infos(HS_Player *player_p, int score)
{
printf("Congrats! Your made a new high score.\n");
printf("What's your name ?\t");
// Read directly. Limit input to 79 chars (allowing room for null terminator).
scanf("%79s", player_p->player_name);
printf("\n");
player_p->player_score = score;
}
Also, just as a "style" tip, you may want to change the member names to just score and name, as the "player" part is implied by the structure type-name itself.
This issue you are having is that you are associating the player name pointer to a variable that goes out of scope when you leave the "player_Infos" function. What you probably would want to do is define the name as a character array in your structure and then use the "strcpy" call in your function instead. Following is a couple of code snippets illustrating that point.
//TYPEDEF STRUCTS
typedef struct
{
int player_score;
char player_name[80];
} HS_Player;
Then, in your function, use the "strcpy" call.
//Player_Infos FUNCTION
void Player_Infos(HS_Player *player_p, int score)
{
char new_name[80];
printf("Congrats! Your made a new high score.\n");
printf("What's your name ?\t");
scanf("%s", new_name);
printf("\n");
player_p->player_score = score;
strcpy(player_p->player_name, new_name);
//player_p->player_name = new_name;
}
When I tested that out, I got a name to appear in the terminal output.
Computer number is smaller!
Your Guess: 4
It's a Match! You chose the same number than the computer.
Number of tries: 8
Highest score: 4 By: Craig
FYI, you will need to include the "string.h" file.
Give that a try.
Name Update
The reason your player.player_name is not getting updated is because you can't assign a string this way in C. When doing player_p->player_name = new_name; you're actually saving in player_p->player_name the memory address of new_name.
Instead, what you want to achieve, is to copy each character of new_name to player_p->player_name and in order to achieve this, you have to change the type of prlayer_name field from char* player_name to char player_name[80], then assign it using, for example, strcpy():
#include <string.h>
// [...]
//TYPEDEF STRUCTS
typedef struct
{
unsigned int player_score;
char player_name[80];
} HS_Player;
// [...]
//Player_Infos FUNCTION
void Player_Infos(HS_Player *player_p, int score)
{
char new_name[80];
printf("Congrats! Your made a new high score.\n");
printf("What's your name ?\t");
scanf("%s", new_name);
printf("\n");
player_p->player_score = score;
strcpy(player_p->player_name, new_name);
}
Data Persistence
To make data (players info) persistent over multiple runs, you have to save the content of the struct to a file.
Example
int Save_Score(char* filename, HS_Player* player)
{
FILE* file = fopen(filename, "w");
if (file == NULL)
{
fprintf(stderr, "\nAn error occurred while opening the file\n");
return -1;
}
if (fprintf(file, "%d %s", player->player_score, player->player_name) < 0)
return -1;
fclose(file);
return 0;
}
int Load_Score(char* filename, HS_Player* player)
{
FILE* file = fopen(filename, "r");
if (file == NULL)
{
fprintf(stderr, "\nAn error occurred while opening the file\n");
return -1;
}
if (fscanf(file, "%d %79s", &player->player_score, player->player_name) < 0)
return -1;
fclose(file);
return 0;
}

scanf a structure from a function, call from same function to scan other structures

Im trying to scanf a structure from file input within a function, and print it using another function.
Ultimately I need to be able to print out the same information that I would from the code that I commented out, but doing so from the functions I have listed in the function prototypes declaration area. I only un-commented 2 of those so I could try baby steps to get something to scan and print using functions. The functions themselves are located at the very bottom.
To finish the scan_auto function, somehow I need to scanf 2 other structures that are part of the main structure. I assume I need to call the functions scan_date and scan_tank from scan_auto, however I am unsure how to do that properly.
Here is the code I have so far...
#include <stdio.h>
#define STRSIZE 20
/* Structure definitions */
typedef struct {
int month,
day,
year;
} date_t;
typedef struct {
double capacity,
current;
} tank_t;
typedef struct {
char make[STRSIZE],
model[STRSIZE];
int odometer;
date_t manuf,
purch;
tank_t tank;
} auto_t;
/* Function prototypes */
/*
int scan_date(date_t *date);
int scan_tank(tank_t *tank);
*/
int scan_auto(auto_t *vehicle, FILE *inp);
/*
void print_date(date_t date);
void print_tank(tank_t tank);
*/
void print_auto(auto_t vehicle);
int main()
{
auto_t vehicle;
int number=0,
i=0,
status=1;
FILE *inp = fopen("autos.txt","r"); /* defining file input */
/* Check to make sure input file is found and readable. */
if(inp==NULL){
printf("Error: Input file - autos.txt - not found!\n");
getch();
return 0;
}
printf("Vehicle Vehicle Odometer Date Date Tank Current\n");
printf("Make Model Reading Purchased Manufactured Capacity Fuel Level\n");
printf("\n----------------------------------------------------------------------------\n\n");
/*******************COMMENTED OUT*************************************
while(status>0){
status=fscanf(inp, "%s%s%d%d%d%d%d%d%d%lf%lf", vehicle.make,
vehicle.model,
&vehicle.odometer,
&vehicle.manuf.month,
&vehicle.manuf.day,
&vehicle.manuf.year,
&vehicle.purch.month,
&vehicle.purch.day,
&vehicle.purch.year,
&vehicle.tank.capacity,
&vehicle.tank.current);
if(status==11){
printf("%-10s%-9s%-10d%2d/%d/%-6d%2d/%d/%-8d%-11.1lf%.1lf\n", vehicle.make,
vehicle.model,
vehicle.odometer,
vehicle.manuf.month,
vehicle.manuf.day,
vehicle.manuf.year,
vehicle.purch.month,
vehicle.purch.day,
vehicle.purch.year,
vehicle.tank.capacity,
vehicle.tank.current);
i++;}
else if(status <11 && status>0){
printf("\nInvalid Input - The next line of data is corrupt.\n");
}
}
******************************************************************************/
scan_auto(&vehicle, inp);
print_auto(vehicle);
/*
print_auto(vehicle);
*/
getch();
return 0;
}
/*********************************************************************************/
int scan_date(date_t *date)
{
int result;
result=scanf("%d%d%d", &(*date).month,
&(*date).day,
&(*date).year);
if (result==3)
result=1;
else if(result !=EOF)
result=0;
return (result);
}
/*********************************************************************************/
double scan_tank(tank_t *tank)
{
int result;
result=scanf("%lf%lf", &(*tank).capacity,
&(*tank).current);
if (result==2)
result=1;
else if(result !=EOF)
result=0;
return (result);
}
/*********************************************************************************/
int scan_auto(auto_t *vehicle, FILE *inp)
{
int result;
result=fscanf(inp, "%s%s%d", (*vehicle).make,
(*vehicle).model,
&(*vehicle).odometer);
if (result==3)
result=1;
else if(result !=EOF)
result=0;
return (result);
}
/*********************************************************************************/
void print_auto(auto_t vehicle)
{
printf("%-10s%-9s%-10d", vehicle.make,
vehicle.model,
vehicle.odometer);
}
The text file (autos.txt) I am using....
Mercury Sable 99842 1 18 2001 5 30 1991 16 12.5
Mazda Navajo 123961 2 20 1993 6 15 1993 19.3 16.7
however I am unsure how to do that properly.
Can you elaborate on what you're unsure? If you're not sure how to assign value to struct member of struct, perhaps this sample code will help you? I combined all of the things together...
Oh, and I changed your *vehicle to *v to make it shorter and easier to read.
Also, since you're accessing member of struct pointer, why don't you use v->xxx instead of (*v).xxx ?
UPDATE 1: You asked how to do it separately. Here it is:
int scan_date(date_t *date, FILE *inp)
{
int result = fscanf(
inp,
"%d%d%d",
&(date->day),
&(date->month),
&(date->year));
return (result == 3);
}
int scan_tank(tank_t *tank, FILE *inp)
{
int result = fscanf(
inp,
"%lf%lf",
&(tank->capacity),
&(tank->current));
return (result == 2);
}
int scan_auto(auto_t *v, FILE *inp)
{
int result = fscanf(
inp,
"%s%s%d",
v->make,
v->model,
&(v->odometer));
result += scan_date(&(v->purch), inp);
result += scan_date(&(v->manuf), inp);
result += scan_tank(&(v->tank), inp);
return (result == 11); // return 0 if true
}

loop over input in C-code and write data to different files using terminal at once

I wrote a C code which extracts data from a binary file which has size around 1 GB. There are 101 (0 to 100)configurations and the C code extracts data for a selected configuration and writes the output in a file. To compile the C code, I give user defined configuration number like this in the terminal:
gcc binary2textperconfig.c -o f.out
./f.out proton-p000-1.bin out1.txt
Then it asks for configuration number:
Enter the configuration number:
After that the data is written in file "out0.txt". Now I want to run this code for all 101 configurations and write those data to files "out0.txt", "out1.txt",...., "out100.txt" etc. I don't know how to do this without typing the configuration numbers 101 times in the terminal. Could any one please help me? Here is my C-code:
#include <stdio.h>
#include<complex.h>
#include<math.h>
#include <stdlib.h>
#include <gsl/gsl_sf_gamma.h>
#include <gsl/gsl_matrix.h>
typedef double complex dcomplex;
//Data is converted to Bigendian using io-general
double constructfloat(char bytes[sizeof(double)/2], int order)
{
double dRes;
char *pc;
int i;
if (order == 0)
for(i=0, pc = (char*) &dRes; i<=sizeof(double)-1 ; i++, pc++)
(*pc) = bytes[i];
else
for(i=sizeof(double)-1, pc = (char*) &dRes; i>=0; i--, pc++)
(*pc) = bytes[i];
return dRes;
}
int main(int argc, char *argv[]){
int configcount = 101;
int mcount = 14;
int tcount = 64;
int d1count = 4;
int d2count = 4;
int pcount = 45;
int userci;
int usermi;
int userpi;
// number of complex numbers per configuration
int unitcountperconfig =(mcount*tcount*d1count*d2count*pcount);
// initialize loop index variables
int ci = 0; //config
int mi = 0; //mass
int ti = 0;
int d1i = 0;
int d2i = 0;
int pi = 0; //momentum
// for holding the result of read operation ( how many units have been read)
int result;
// for holding the data read from file
char * cbuff;
// input file handle from where binary data is read
FILE * fin = fopen(argv[1],"rb");
// if the input file cannot be read for reading, close opened file handles, show an error message to the user, and exit
if (fin==NULL)
{
fputs ("Error opening input file\n",stderr);
exit (1);
}
FILE * fout = fopen(argv[2],"wt");
// if the output file cannot be opened for writing, close opened file handles, show an error message to the user, and exit
if (fout==NULL)
{
fclose(fin);
fputs ("Error opening output file\n",stderr);
exit (1);
}
// take input from the user
// take input from the user
printf("Enter the configuration number: ");
scanf("%d",&userci);
// allocate memory to contain the chunk of data for a time slice:
cbuff = (char*)malloc(sizeof(dcomplex)*unitcountperconfig );
// show error message and exit if memory allocation failed
if(cbuff == NULL)
{
fputs("Buffer allocation failed.", stderr);
exit(1);
}
// variable to hold a complex number read from the file
dcomplex aComplexNumber;
dcomplex sumpertimeslice[tcount];
// loop on time slices
for( ci = 0; ci< configcount ; ci++){
// index of the complex number being read
unsigned int cNumberIdx = 0;
// debugging message
printf("reading data for configuration: %d\n",ci);
// perform read operation to read the desired chunk of data
result = fread(cbuff, sizeof(char), sizeof(dcomplex)*unitcountperconfig, fin );
// if size of data successfully read is not equal to what we wanted to read, notify the user and exit
if (result != sizeof(dcomplex)*unitcountperconfig) {
fputs ("data reading error\n",stderr);
exit (3);
}
double realP;
double imagP;// variable to hold real and imaginary part of the complex number
double realPSum;
double imagPSum;// variable to hold sum of real and sum of imaginary part of the current sum per time slice
for (mi =0; mi< mcount ; mi++){
for (ti =0; ti< tcount ; ti++){
// array to hold trace for each time slice
sumpertimeslice[ti] = 0.0 + 0.0*_Complex_I;
for (d1i =0; d1i < d1count ; d1i++){
for (d2i =0; d2i < d2count ; d2i++){
for (pi =0; pi < pcount ; pi++){
aComplexNumber = constructfloat( &cbuff[cNumberIdx], 0 ) + constructfloat( &cbuff[cNumberIdx+ ((int)sizeof(dcomplex))/2 ], 0 )*_Complex_I;
if (ci== userci)
{
cNumberIdx += (int)sizeof(dcomplex);
if (cimag(aComplexNumber)>0)
{fprintf( fout, "%d,%d,%d,%d,%d,%d,%e+%ei\n" ,ci+1, mi+1,ti+1, d1i+1,d2i+1,pi+1,creal( aComplexNumber ),cimag( aComplexNumber ) );}
else
{fprintf( fout, "%d,%d,%d,%d,%d,%d,%e%ei\n" ,ci+1, mi+1,ti+1, d1i+1,d2i+1,pi+1,creal( aComplexNumber ),cimag( aComplexNumber ) );}
}
}
}
}
}
}
}
// free the allocated memory
free(cbuff);
// close the opened file handles
fclose(fin);
fclose(fout);
//fclose(complexNumberFileP);
}
Use the seq utility to generate a list of number between 0 & 100, and send it as a string to stdin.
for CNUMBER in $(seq 0 100); do
./f.out proton-p000-1.bin out${CNUMBER}.txt <<< "${CNUMBER}"
done
or
for CNUMBER in $(seq 0 100); do
echo $CNUMBER | ./f.out proton-p000-1.bin out${CNUMBER}.txt
done

Error with content being read out of file

Hello fellow programmers i am trying to understand what exactly is happening in this area of my code.
Problem: I read some contents into a file , then i am trying to read back the contents out of the file just to make sure its the right contents i had put into the file but it is not giving me the correct output, so i am a little confused here is the code(saved content as binary) :
typedef struct acc
{
int id_no;
int pin;
float bal;
}Acc;
int Crte_acc(FILE *flepss)
{
int i,cnt;
Acc user[1000];
cnt = 1000;
for (i=1;i<1000;i++)
{
cnt+=1;
user[i].id_no = cnt;
user[i].bal=1000;
user[i].pin=0000;
fwrite(&user[i].id_no,sizeof(int),1,flepss);
fwrite(&user[i].pin,sizeof(int),1,flepss);
fwrite(&user[i].bal,sizeof(int),1,flepss);
}
return fclose(flepss);
}
Yea so above is the code that takes a file pointer and a count to keep the id to increase by 1 ( 1001,1002 etc), bal and pin required that i set the var with those digits.So i am wondering whats the problem, this is the code of me displaying the contents.
void DisplyFile()
{
FILE *dfp;
int x;
Acc pruser[1000];
dfp = fopen("Account.dat","rb");
fseek(dfp,0,SEEK_SET);
while (1)
{
if(!feof(dfp))
{
for (x=1;x<1000;x++)
{
fread(&pruser[x].id_no,sizeof(pruser[x].id_no),1,dfp);
fread(&pruser[x].pin,sizeof(pruser[x].pin),1,dfp);
fread(&pruser[x].bal,sizeof(pruser[x].bal),1,dfp);
printf("%d ",pruser[x].id_no);
printf("%d ",pruser[x].pin);
printf("%.2f\n\n",pruser[x].bal);
}
}
else
{
break;
}
}
}
EDIT: By contents coming out wrong i mean , giving me garbage values as to show that my write to file was not saved.
The problem may come from a missing fclose or fopen...
There is almost nothing to do to build something that works.
Three things to check :
-Does a fopen correspond to a fclose ?
-Are opening types similar ? Are both "wb" and "rb" used ?
-Another point is fwrite(&user[i].bal,sizeof(int),1,flepss);...bla is a float. float and int may have the same sizeof, but...It is safer to assume that it is not always the case !
#include <stdio.h>
typedef struct acc
{
int id_no;
int pin;
float bal;
}Acc;
int Crte_acc()
{
FILE *flepss;
int i,cnt;
Acc user[10];
cnt = 1000;
flepss = fopen("Account.dat","wb");
for (i=1;i<10;i++)
{
cnt+=1;
user[i].id_no = cnt;
user[i].bal=10;
user[i].pin=0000;
fwrite(&user[i].id_no,sizeof(int),1,flepss);
fwrite(&user[i].pin,sizeof(int),1,flepss);
fwrite(&user[i].bal,sizeof(float),1,flepss);
}
return fclose(flepss);
}
void DisplyFile()
{
FILE *dfp;
int x;
Acc pruser[10];
dfp = fopen("Account.dat","rb");
fseek(dfp,0,SEEK_SET);
while (1)
{
if(!feof(dfp))
{
for (x=1;x<10;x++)
{
fread(&pruser[x].id_no,sizeof(pruser[x].id_no),1,dfp);
fread(&pruser[x].pin,sizeof(pruser[x].pin),1,dfp);
fread(&pruser[x].bal,sizeof(pruser[x].bal),1,dfp);
printf("%d ",pruser[x].id_no);
printf("%d ",pruser[x].pin);
printf("%.2f\n\n",pruser[x].bal);
}
}
else
{
break;
}
}
fclose(dfp);
}
int main()
{
Crte_acc();
printf("file printed\n");
DisplyFile();
printf("end file read 1\n");
DisplyFile();
printf("end file read 2\n");
return 0;
}
To compile : gcc main.c -o main
Bye,

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