HELP how do i create multiple sine waves

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <cstdlib>
#include <iostream>
#include <math.h>
#include <cstdio>
#include <stdio.h>
#include "dp_lib.h"
int main() {
	int A =1;
  float* data; 
  long int num_samples;
  float f=4400; frequency 
  float pi= 3.141;	
  float fs = 44100;//sample rate
  

	num_samples = 2 * fs; 

data = (float*) allocate_memory(num_samples);

FILE* fp = fopen("audio_wav", "wb" );


for (int n=0; n < 8000; n++) 

{
data[n] = A*sin(2*pi*44100*n*20/fs) ;
}
for (int n= 8001; n <16000; n++) 

{
data[n] = A*sin(2*pi*44100*n*30/fs) ;
}

write_wav_file(data,num_samples,fs,fp);

free(data);

cout << "\nMemory now released";
	
	return 0;
}


Hi im new to coding but ive written this code for an assignment and it creates 2 sine waves and adds them together but i want to be able to create a range of different sine waves at different frequencies and play them one after the other like in my code,but with the end result being that i would like each sine wave to represent a different note, so when your on the the console screen the user will be able to choose from a select number of notes and input them in any order so that the WAV file produced plays the sine waves in the order the user chooses so they can make a simple tune. but my code only plays it in the order it is in the code
any help or advice welcome
Last edited on
Note, that I don't have "dp_lib.h". I cannot compile this and verify the validity of this program. This is loosely based on the snippet you provided. Excuse the lack of error checking/handling and documentation.
Please let me know if it works or doesn't work - either way, feel free to ask questions.

Almost forgot, this program doesn't meet all your requirements, because as you can see, the array containing the frequencies is hardcoded.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#define NOMINMAX
#include <iostream>
#include <limits>
#include <stdio.h>
#include "dp_lib.h"

typedef unsigned short BitDepth;
typedef unsigned __int64 QWORD;

int main(int argc, char* argv[]) {

	const unsigned int samplerate = 44100;
	const unsigned short channels = 2;

	const double pi = 3.14159265;
	const BitDepth amplitude = std::numeric_limits<BitDepth>::max() * 0.5;

	const unsigned short n_frequencies = 8;
	const unsigned short n_seconds_each = 1;

	float frequencies[n_frequencies] = { 55.0, 110.0, 220.0, 440.0, 880.0, 1760.0, 3520.0, 7040.0 };

	const QWORD n_samples = channels * samplerate * n_frequencies * n_seconds_each;
	BitDepth* data = new BitDepth[n_samples]{0};

	FILE* file = fopen("audio_wave", "wb");
	

	QWORD index = n_samples / n_frequencies;
	for (unsigned short i = 0; i < n_frequencies; ++i) {

		float freq = frequencies[i];
		double d = (samplerate / freq);
		QWORD c = 0;
		for (QWORD j = index*i; j < index*(i + 1); j += 2) {
			double deg = 360.0 / d;
			data[j] = data[j + (channels - 1)] = sin((c++*deg)*pi / 180.0) * amplitude;
		}
	}

	write_wav_file(data, n_samples, samplerate, file);

	delete[] data;

	std::cout << "Memory released." << std::endl;
	std::cin.get();
	return 0;
}
thanks for trying to help but its just confused me more, like you said you couldn't verify it so i took your code and compiled it to see what would happen and it came up with a few error messages
[Error] cannot convert 'BitDepth* {aka short unsigned int*}' to 'float*' for argument '1' to 'void write_wav_file(float*, long unsigned int, long unsigned int, FILE*)'
[Error] 'sin' was not declared in this scope

it also keeps pulling the "dp_lib.h" up which im guessing is because the two codes dont agree with each other

this is the code "dp_lib.h"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <cstdlib>
#include <iostream>
#include <string>
#include <iomanip>
#include <locale>
#include <sstream>
#include <stdio.h>
using namespace std;

//  declare stucture for wav file header elements
struct wav_header
{
       char chunk_id[4];
       unsigned long chunksize;
       char format[4];
       char subchunk1_id[4];
       unsigned long subchunk1_size;
       unsigned short audio_format;
       unsigned short num_channels;
       unsigned long sample_rate;
       unsigned long byte_rate;
       unsigned short block_align;
       unsigned short bits_per_sample;
       char subchunk2_id[4];
       unsigned long subchunk2_size;
} wavfile;
 
 /* This function allocates the values to the WAV file header elements and writes the wav file. */      
void write_wav_file(float* data, unsigned long no_samples, unsigned long sample_rate, FILE* fptr)
{  
// assign header values
    wavfile.chunk_id[0] = 'R';
    wavfile.chunk_id[1] = 'I';
    wavfile.chunk_id[2] = 'F';
    wavfile.chunk_id[3] = 'F';
    wavfile.format[0] = 'W';
    wavfile.format[1] = 'A';
    wavfile.format[2] = 'V';
    wavfile.format[3] = 'E';
    wavfile.subchunk1_id[0] = 'f';
    wavfile.subchunk1_id[1] = 'm';
    wavfile.subchunk1_id[2] = 't';
    wavfile.subchunk1_id[3] = ' ';
    wavfile.subchunk1_size = 16;
    wavfile.audio_format = 1;
    wavfile.num_channels = 1;
    wavfile.sample_rate = sample_rate;
    wavfile.byte_rate = 2*sample_rate;
    wavfile.bits_per_sample = 16;
    wavfile.block_align = wavfile.bits_per_sample*wavfile.num_channels/8;
    wavfile.subchunk2_id[0] = 'd';
    wavfile.subchunk2_id[1] = 'a';
    wavfile.subchunk2_id[2] = 't';
    wavfile.subchunk2_id[3] = 'a';
    wavfile.subchunk2_size = wavfile.block_align*no_samples;
    wavfile.chunksize = 36 + wavfile.subchunk2_size;

      if (fptr != NULL) // check if file is open ok
      {
      // Write file data
      fwrite(&wavfile, sizeof(wavfile), 1, fptr); // write header
      
      /* Convert samples from floating 0 - 1 range to quantised 16 bit values */
      short* quantised;
       quantised =  (short*) malloc(no_samples*sizeof(short));
       for (int i=0;i<no_samples; i++)
       quantised[i] = (short) (data[i]*32767);
      
      
      /* Now write all quantised samples to WAV file  */
      fwrite(quantised, sizeof(short), no_samples, fptr); // write audio data
      free (quantised);
      cout << "Written WAV file successfully\n";
       }
       else cout<< "Unable to write file";
       
}

// Funtion to allocate memory for audio sample data
void* allocate_memory(unsigned long data_length)
{
       void* data;
       data =  (void*) malloc(data_length*sizeof(float));
       return data;
}
      
          
          
 /* This function takes the step number and floating point value, */
 /* and converts them to text to put into a CSV file for Excel  */ 
      
void write_CSV(int step, float value, FILE* fptr)
{
      if (fptr != NULL)
      {
        string step_text, value_text;      // declare strings which will contain the result
        ostringstream convert1;            // assign stream used for the conversion
        convert1 << step;                  // insert the textual representation of 'Number' in the characters in the stream
        step_text = convert1.str();        // set 'Result' to the contents of the stream
        
        
        ostringstream convert2;           // stream used for the conversion
        convert2 << value;                // insert the textual representation of 'Number' in the characters in the stream
        value_text = convert2.str();      // set 'Result' to the contents of the stream
//        cout << step_text <<"\t"<<value_text<<"\n";
        
        char comma=',';
        char newline = 10;
        for(int i=0; i<step_text.length(); i++)
                fwrite(&step_text[i], sizeof(char),1, fptr); // write the step value
        fwrite(&comma, sizeof(char), 1, fptr);
        for(int i=0; i<value_text.length(); i++)
                fwrite(&value_text[i], sizeof(char), 1, fptr); // write the sample value
        fwrite(&newline, sizeof(char), 1, fptr);
        }
        else
            cout << "Unable to write file";
}

/*  Find the nth root of a number (used to find pitch: one semi-tone = 12 root of 2, times or divide by the frequency)  */
double root(double radicand,double degree)
{
	return pow(radicand,1.0/degree);
}


like i said thanks for trying to help.
i dont know if it makes but im using a windows pc with DEV C++
But where does "dp_lib.h" come from? It doesn't come as standard with Dev C++, does it? Is it available (together with any associated files) as a free download somewhere please?
sorry i dont know it was given to me for this assignment
Do you need to use dp_lib.h? I just tried to modify my code to fit the requirements imposed by this header file, and my god is it ugly. If it's allowed for you to write your own header or use another, then I would be happy to slap something sensible together for you.
thanks for trying to help ive decided to change direction and go for a much simpler idea but thanks for trying to help me. maybe u can help me with another problem

i know this creates a simple sinewave
data[n] = A*sin(2*pi*n*100/fs) ;

and this a rudimentary square wave
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
data[n] = (A)*sin(2*pi*n*f/fs) 
	 + (A/3)*sin(2*pi*n*(f*3)/fs) 
	 + (A/5)*sin(2*pi*n*(f*5)/fs) 
	 + (A/7)*sin(2*pi*n*(f*7)/fs) 
	 + (A/9)*sin(2*pi*n*(f*9)/fs) 
	 + (A/11)*sin(2*pi*n*(f*11)/fs) 
	 + (A/13)*sin(2*pi*n*(f*13)/fs) 
	 + (A/15)*sin(2*pi*n*(f*15)/fs) 
	 + (A/17)*sin(2*pi*n*(f*17)/fs) 
	 + (A/19)*sin(2*pi*n*(f*19)/fs) 
	 + (A/21)*sin(2*pi*n*(f*21)/fs)
	 + (A/23)*sin(2*pi*n*(f*23)/fs) 
	 + (A/25)*sin(2*pi*n*(f*25)/fs) 
	 + (A/27)*sin(2*pi*n*(f*27)/fs) 
	 + (A/29)*sin(2*pi*n*(f*29)/fs) 
	 + (A/31)*sin(2*pi*n*(f*31)/fs);


do you no how i could turn that into a saw tooth wave
a rudimentary square wave

You need to be careful with expressions like this, (A/3) where A is of type int, as this gives an integer division, in this case with int A= 1; the result will be zero. A solution is to change A to type double.

It is possible to synthesise a triangle wave using a similar summation of harmonics:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    data[n]  = 8.0/(pi*pi) * (
             + (A)             * sin(2*pi*n*f/fs) 
             - (A/(3.0 * 3.0)) * sin(2*pi*n*(f*3.0)/fs) 
             + (A/(5.0 * 5.0)) * sin(2*pi*n*(f*5.0)/fs) 
             - (A/(7.0 * 7.0)) * sin(2*pi*n*(f*7.0)/fs) 
             + (A/(9.0 * 9.0)) * sin(2*pi*n*(f*9.0)/fs) 
             - (A/(11.0*11.0)) * sin(2*pi*n*(f*11.0)/fs) 
             + (A/(13.0*13.0)) * sin(2*pi*n*(f*13.0)/fs) 
             - (A/(15.0*15.0)) * sin(2*pi*n*(f*15.0)/fs) 
             + (A/(17.0*17.0)) * sin(2*pi*n*(f*17.0)/fs) 
             - (A/(19.0*19.0)) * sin(2*pi*n*(f*19.0)/fs) 
             + (A/(21.0*21.0)) * sin(2*pi*n*(f*21.0)/fs)
             - (A/(23.0*23.0)) * sin(2*pi*n*(f*23.0)/fs) 
             + (A/(25.0*25.0)) * sin(2*pi*n*(f*25.0)/fs) 
             - (A/(27.0*27.0)) * sin(2*pi*n*(f*27.0)/fs) 
             + (A/(29.0*29.0)) * sin(2*pi*n*(f*29.0)/fs) 
             - (A/(31.0*31.0)) * sin(2*pi*n*(f*31.0)/fs) );  

See http://en.wikipedia.org/wiki/Square_wave#Examining_the_square_wave
http://en.wikipedia.org/wiki/Triangle_wave#Harmonics

However, unless you have a particular interest in this form of synthesis, you can instead use a function to give a perfect square or triangle wave. For example,
1
2
3
4
5
6
7
8
9
10
11
double square(double x)
{
    const double pi = 3.1415926535897932385;
    
    long  whole = long(x / pi);
    
    if (whole % 2 == 0)
        return 1.0;
    else 
        return -1.0;
}



1
2
3
4
5
6
7
8
9
10
11
12
double triangle(double x)
{
    const double pi = 3.1415926535897932385;
    
    long  whole = long(x / pi);
    double fraction = (x - pi * whole) / pi;
    
    if (whole % 2 == 0)
        return 2.0 * (fraction - 0.5);
    else 
        return 2.0 * (0.5 - fraction);
}


To use these, simply replace the sin function with the required alternative;
example, data[n] = A*triangle(2*pi*n*f/fs);
or data[n] = A*square(2*pi*n*f/fs);
#include "stdafx.h"
02
#include <stdio.h>
03
#include <tchar.h>
04
#include <iostream>
05
#include <math.h>
06
#include <conio.h>
07
#include <iomanip>
08
#include <time.h>
09
#include <stdlib.h>
10
#include <dos.h>
11
// We need to output stuff, and we need the sine function
12

13
using namespace std;
14

15
int sinewave()
16
{
17
srand((unsigned)time(0));
18
// declarations
19
FILE *fptr;
20
char fileName[50] = "";
21
double freq;
22
double gain;
23
double phase;
24
double bias;
25
double noise;
26
char save;
Topic archived. No new replies allowed.