Fixing my Mixer project

closed account (365X92yv)
So I know that what I'm about to post seems like an insane amount of code for one post. Bear with me though, most of it is finished. I just need to get one or two things written correctly and it should work. Right now, I can't get my command object to use its data members to correctly call the respective method using the respective wav file. I've been playing around with the syntax and for the life of me can't seem to figure it out. I realize that some of the code I have isn't working correctly, namely the Double(), Half(), Mix(), Reverse(), and Echo() methods all have inconsistencies or flat-out malficiencies. My focus right now though is to get the command class object, with the user's input, and use that data to call the correct method and use the right wav file.

EDIT: What you'll see is I have a wav class, that handles creating the wav files. Then I have a WavContainer class that holds and "manages" a number of wav files. And then I've got the command class that creates an object to handle the user's input. I need to use the command object's data to call the methods to do stuff to the pertaining wav file and wav method.


Here's the code:

main.cpp
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;

#include "wav.h"
#include "WavContainer.h"

class command
{
public:
	string option, newSound;
	int place, placeTwo;
	WavContainer wave;
	command();
	void input();
	int selection(WavContainer &waveCont);
};

command::command()
{
	option = "";
	newSound = "";
	place = 0;
	placeTwo = 0;
}

void command::input()
{
	string input; // Holds the user's input for parsing.
	cout << "cmd> ";
	string peek = ""; // String to hold the first character in input
	int blankCnt = 0; // Used in case the for loop encounters spaces in string input.
	getline(cin, input); // Gets the user's input from the cin
	for(unsigned int i=0;i<input.length();i++)
	{
		peek = input[ i ]; // gets the first character in the input string, stores in peek
		if(peek != " ") // if its a blank
		{
			if((peek >= "a") && (peek <= "z")) //if its a letter between a -> z
			{
				if(blankCnt == 0) // if its a blank, increases count
					option.append( peek ); // appends the char in peek to the option string
				else
					newSound.append( peek ); //if it hits a space, starts storing in the newSound string
			}
			else if((peek >= "1") && (peek <= "9")) // if it hits a number
			{
				if((place >= 1) && (place <= 9)) // if place has a number in it
					placeTwo = atoi( peek.c_str() ); // stores in placeTwo
				else								// if not, stores in place
					place = atoi( peek.c_str() ); 
			}
		}
		else
			blankCnt++; // increments blankCnt
	}
	// COUT CHECK
	cout << "option: " << option << endl
		<< "place: " << place << endl 
		<< "placeTwo: " << placeTwo << endl
		<< "newSound: " << newSound << endl;
}

int command::selection(WavContainer &waveCont) // NOT DONE, DOESN'T CALL THE METHODS
{
	int pos;
	pos = waveCont.GetPos();
	// Use the prompt object to call the methods	
	if(option == "play")
	{
		cout << "PLAY" << endl;
		//CALL THE PLAY METHOD
		// USE THE PLACE INT TO CALL PLAY METHOD ON RIGHT WAV
		return pos;
	}
	else if(option == "delete")
	{
		cout << "DELETE" << endl;
		//CALL THE DELETE METHOD
	}
	else if(option == "reverse")
	{
		cout << "REVERSE" << endl;
		//CALL THE REVERSE METHOD
	}
	else if(option == "half")
	{
		cout << "HALF" << endl;
		//CALL THE HALF METHOD
	}
	else if(option == "double")
	{
		cout << "DOUBLE" << endl;
		//CALL THE DOUBLE METHOD
	}
	else if(option == "mix")
	{
		cout << "MIX" << endl;
		//CALL THE MIX METHOD
	}
}

int main()
{
	// Create the wav container with the initial amount of wav files
	WavContainer waves( 6 );

	// Get the wav files
	Wav cde("sounds\\cde.wav");
	Wav crow("sounds\\crow.wav");
	Wav door("sounds\\door.wav");
	Wav luke("sounds\\luke.wav");
	Wav water("sounds\\water.wav");
	Wav welcome("sounds\\welcome.wav");

	//checks to test the wav effects
	door.Play();
	//door.Reverse();
	//door.Half();
	//door.Double();
	//door.Mix();
	//door.Echo();

	// Add the wav files to the container
	waves.Add(cde);
	waves.Add(crow);
	waves.Add(door);
	waves.Add(luke);
	waves.Add(water);
	waves.Add(welcome);

	// Checks to see what is added and how big it is
	cout << "There are " << waves.Size() << " wave files to use." << endl << endl;
	
	// CALL THE SHOW SELECT FUNCTION
	cout << "Selection: " << endl;
	waves.Show();

	// COUT FOR STRING TO SELECT
	command prompt;
	prompt.input();

	int pos;
	pos = prompt.selection( waves );

	
	return 0;
	system("pause");
}


There's more code. See following posts.
Last edited on
closed account (365X92yv)
wav.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
#ifndef INCLUDE_WAV
#define	INCLUDE_WAV

#include <iostream>
using namespace std;

class Wav
{
public:
	// constructors
	Wav();
	Wav( string filename );
	~Wav();
	Wav( const Wav& other );
	Wav& operator=( const Wav& other);

	//methods
	void Play(); // method to play the sound
	void Reverse();	// method to reverse the sound
	void Half(); // method to half-time the sound
	void Double(); // method to double-time the sound
	void Mix(); // method to mix the two sounds
	void Echo(); // metohd to echo the sound

	string toString(int &position);

private:
	// Variables	
	// sample storage
	double * samples;
	unsigned int sampleCount;

	// other important info from the WAV format
	double sampleRate;
    unsigned int bitsPerSample;
    unsigned int channels;
	string fileName;
};

#endif 


wav.cpp
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#include <string>
#include <sstream>
#include "wav.h"
#include "wav_in.h"
#include "wav_out.h"
#include "windows.h"

Wav::Wav()
{
	sampleRate = 0;
    bitsPerSample = 0;
    channels = 0;
	sampleCount = 0;
	fileName = "";
	samples = NULL;
}

Wav::Wav( string filename )
{
	// use WAV_IN object to read WAVE file
	WAV_IN infile( filename.c_str() );
	fileName = filename;
	// get WAVE parameters from the infile object
	sampleRate = infile.get_sample_rate_hz();
    bitsPerSample = infile.get_bits_per_sample();
    channels = infile.get_num_channels();
	sampleCount = infile.get_num_samples();

	samples = new double[sampleCount];
	// read the sample values and store them in samples
	for( unsigned int i=0; i<sampleCount; i++ )
	{
		samples[i] = infile.read_current_input();
    }
}

Wav::~Wav()
{
	cout << "WAV DESTRUCTION!" << endl;
	cout << fileName << endl;
	if(samples != NULL)
		delete []samples;
}

Wav::Wav( const Wav& other )
{
	cout << "MIMIC, AWAYYYYYYY" << endl;
	double *samplesCopy = new double[other.sampleCount];
	sampleRate = other.sampleRate;
	bitsPerSample = other.bitsPerSample;
    channels = other.channels;
	sampleCount = other.sampleCount;
	fileName = other.fileName;
	for( unsigned int i=0; i<sampleCount; i++ )
	{
		samplesCopy[ i ] = other.samples[ i ];
    }
	samples = samplesCopy;
	delete []samplesCopy;
}

Wav& Wav::operator=( const Wav& other)
{
	if(this != &other)
	{
		double *tempWav = new double[other.sampleCount];
		sampleRate = other.sampleRate;
		bitsPerSample = other.bitsPerSample;
	    channels = other.channels;
		sampleCount = other.sampleCount;
		fileName = other.fileName;
		for( unsigned int i=0; i<sampleCount; i++ )
		{
			tempWav[ i ] = other.samples[ i ];
		}
	}
	return *this;
}

void Wav::Reverse()
{
	// iterate over half the samples
	for( unsigned int i=0; i<sampleCount/2; i++ )
	{
		// swapping with the other half
		double temp = samples[i];
		samples[i] = samples[sampleCount-i-1];
		samples[sampleCount-i-1] = temp;
	}
}

void Wav::Play() // Play() writes the wav file, needs to be called first
{
	// setup a WAV_OUT object to write the file to disk
	WAV_OUT outfile( sampleRate, bitsPerSample, channels );

	// add the samples to the outfile object
	for( unsigned int i=0; i<sampleCount; i++ )
	{
		outfile.write_current_output( samples[i] );
    }

	// and write it out to a temporary file
	outfile.save_wave_file( "out.wav" );
 
	// call the windows API to play that temporary file
	PlaySound( TEXT("out.wav"), NULL, SND_FILENAME );
}

void Wav::Half() // HALVES THE WAV FILE
{
	// setup a WAV_OUT object to write the file to disk
	WAV_OUT outfile( sampleRate, bitsPerSample, channels );

	// add the samples to the outfile object
	for( unsigned int i=0; i<sampleCount; i++ )
	{
		if((i % 2) == 0)
		{
			outfile.write_current_output( samples[i] );
		}
    }

	// and write it out to a temporary file
	outfile.save_wave_file( "out.wav" );
 
	// call the windows API to play that temporary file
	PlaySound( TEXT("out.wav"), NULL, SND_FILENAME );
}

void Wav::Double() // NOT COMPLETE, OR CORRECT
{
	// iterate over the samples 
	double *temp = new double[sampleCount*2];
	for( unsigned int i=0; i<sampleCount; i++ )
	{
		temp[2 * i] = temp[2 * i + 1] = samples[i];
	}
}

void Wav::Mix() // HAVE ONLY COPIED THE REVERSE METHOD INTO HERE
{
	// iterate over half the samples
	for( unsigned int i=0; i<sampleCount/2; i++ )
	{
		// swapping with the other half
		double temp = samples[i];
		samples[i] = samples[sampleCount-i-1];
		samples[sampleCount-i-1] = temp;
	}
}

void Wav::Echo() // ONLY COPIED THE REVERSE METHOD INTO HERE
{
	// iterate over half the samples
	for( unsigned int i=0; i<sampleCount/2; i++ )
	{
		// swapping with the other half
		double temp = samples[i];
		samples[i] = samples[sampleCount-i-1];
		samples[sampleCount-i-1] = temp;
	}
}

string Wav::toString(int &position)
{
	ostringstream oss;

	oss << (position + 1) << ": " << fileName ;

	return oss.str();
}


WavContainer.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
#include "wav.h"

class WavContainer
{
private:
	Wav *Wavs;
	int size, position;
public:
	// CONSTRUCTORS
	WavContainer();
	WavContainer(int);
	//WavContainer& operator=( const WavContainer& rhs );
	//WavContainer( const WavContainer& to_copy );

	// DESTRUCTOR
	~WavContainer();

	// METHODS
	void Add(Wav &);
	void Copy();
	void Expander();
	int Size();
	void Show();
	void Remove(int pos);
	int GetPos() { return position; };
	void Play(int pos);
};


WavContainer.cpp
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
#include <iostream>
#include <string>
#include "WavContainer.h"

WavContainer::WavContainer()
{
	cout << "Default Constructor" << endl;
	size = 0;
	position = 0;
	Wavs = NULL;
}

WavContainer::WavContainer(int s)
{
	cout << "Int Constructor" << endl;
	size = s;
	Wavs = new Wav[size];
	position = 0;
}

WavContainer::~WavContainer()
{
	cout << "WAVS DESTRUCTION" << endl;
	cout << &Wavs << endl;
	if(Wavs != NULL)
	{
		delete []Wavs;
	}
}

void WavContainer::Add(Wav &wav)
{
	if(position == size)
	{
		Expander();
		Wavs[position] = wav;
		position++;
		// call a method to create a new array, new size, and then copy
		// then take it and delete the old one.
	}
	else
	{
		Wavs[position] = wav;
		position++;
	}
}

int WavContainer::Size() {	return size; }

void WavContainer::Show()
{
	for(int i=0;i<size;i++)
	{
		cout << Wavs[i].toString( i ) << endl;
	}
	//prints out all items on the list.
}

void WavContainer::Remove(int pos)
{
//remove item at pos, then move items up one slot
	Wavs[ pos ] = Wavs [ pos + 1];
	cout << Wavs[ pos ].toString( pos ) << endl;
	for(int i = pos;i< size;i++)
	{
		Wavs[ i ] = Wavs[ i + 1 ];
		cout << Wavs[ i ].toString( pos ) << endl;
	}
	size--;
}		

void WavContainer::Expander()
{
	Wav* newArray = new Wav[size + 1]; // Create new array, twice the size
	for(int i=0;i<size;i++)
	{
		newArray[ i ] = Wavs[ i ];
	}
	size++;
	delete [] Wavs;
	Wavs = newArray; // reset pointer focus
}

void WavContainer::Play(int pos)
{

}
closed account (365X92yv)
Still not working. Noone?
Your code is overwhelming and the description of the problem is a little unclear, so it's hard to help. This is probably why nobody has replied yet.

Right now, I can't get my command object to use its data members to correctly call the respective method using the respective wav file.


Can you elaborate on this more?

What is your command class supposed to be doing?
What is it actually doing?

Examples are also really helpful. IE "when I input 'foo' it does 'bar' but I want it to do 'baz'"

closed account (365X92yv)
command functions by creating an object with four data members. it parses a string that holds what is put on the istream. The command class is used to get the users input. It is purely used for that. What the rest is simple.

What I want to do is ask the user what he wants to do. Then once I get the user telling me what to do, I would like to use that input stored in a command object, and use it as parameters for calling methods in my wav class. The problem I'm having is the fact that command has no connection with WavContainer or the wav classes. Its unable to handle anything from the command class. So when I want to use the first data member in command, option, and use that in a method to call the correct method in wav class. Its really complicated so I'll apologize ahead of time for the nonsense. I'm trying my best to keep it as simple as possible.
blankCnt++; // increments blankCnt

Comments like that make code harder to read, and you've already posted far more code than you needed to.

If I understand what you're asking for it's help implementing the command::selection function, which you've made no attempt to do other than writing a few comments?
closed account (365X92yv)
Forget it. I'll just fuckin' do it myself.
So looking at the WaveContainer class... you have this public interface.

1
2
3
4
5
6
7
8
void Add(Wav &);
void Copy();
void Expander();
int Size();
void Show();
void Remove(int pos);
int GetPos() { return position; };
void Play(int pos);


So for "Play" inside your selection command, based on the users input data, call waveCont.Play(userselectedInput);

What is the question again?

You need to modifier your container to give you the interface command can use to do what you need. Either modify the container directly, or create an interface that the container inherits from and implements those methods (google adapter pattern)... you have the code there, you know what you want to be able to pass as parameters, just create the interface for it.
Last edited on
Topic archived. No new replies allowed.