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 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
/*
* File: main.cpp
* Author: cmisip
*
* Created on March 4, 2017, 2:41 PM
*/
#include <ao/ao.h>
#include <mpg123.h>
#include <string>
#include <iostream>
#include <fcntl.h>
#include <cstring>
#include <unistd.h>
#define BITS 8
class audio_sample {
public:
audio_sample(){ std::cout << "Default Constructor" << std::endl;};
audio_sample(const char* ifile, ao_device * a_idev):a_dev(a_idev){
std::cout << "Parameterized Constructor" << std::endl;
init();
filename=ifile;
process();
};
void init(){
mh = mpg123_new(NULL, &err);
buffer_size = mpg123_outblock(mh);
buffer = (unsigned char*) malloc(buffer_size * sizeof(unsigned char));
}
void process() {
int fnum = open(filename, O_RDONLY);
if(fnum < 0){
printf("ERROR opening file: %s\n", strerror(fnum));
exit(0);
}
int retval=mpg123_open(mh, filename);
close(fnum);
mpg123_read(mh, buffer, buffer_size, &done);
}
audio_sample(const audio_sample &other){ //LESSON: must be const parameter
std::cout << "Copy constructor ..calls copy assignment"<< std::endl;
*this=other;
}
audio_sample & operator=(const audio_sample &other) { //LESSON: must be const parameter
std::cout << "Copy Assignment operator "<< std::endl;
if(this != &other ){
this->~audio_sample(); //LESSON: OK to delete a null pointer
init();
buffer_size=other.buffer_size;
filename=other.filename;
a_dev=other.a_dev;
process();
}
return *this;
}
audio_sample( audio_sample &&other){ //LESSON: cannot be const parameter
std::cout << "Move constructor ..calls move assignment"<< std::endl;
*this=std::move(other);
}
audio_sample & operator=(audio_sample &&other) { //LESSON: cannot be const parameter
std::cout << "Move Assignment operator "<< std::endl;
if(this != &other ){
this->~audio_sample(); //LESSON: OK to delete a null pointer
//METHOD 1 : std::move --> WORKS
/*mh=std::move(other.mh);
other.mh=nullptr; //LESSON: std::move does not set moved from pointer to nullptr
buffer=std::move(other.buffer);
other.buffer=nullptr;
buffer_size=std::move(other.buffer_size);
filename=std::move(other.filename);
a_dev=std::move(other.a_dev);
*/
//METHOD 2: copy values -->WORKS
/*mh=other.mh;
other.mh=nullptr;
buffer_size=other.buffer_size;
buffer=other.buffer;
other.buffer=nullptr;
filename=std::move(other.filename);
a_dev=std::move(other.a_dev);
*/
//METHOD 3: in place construction --> WORKS
new (this) audio_sample (other); //calls copy constructor which calls copy assignment
//puts the created object in memory allocated for this
//Technically, this seems like move assignment
}
return *this;
}
~audio_sample(){
std::cout << "Destructor" << std::endl;
free(buffer);
mpg123_close(mh);
mpg123_delete(mh);
}
void play(){
mpg123_seek(mh,0,SEEK_SET);
/* decode and play */
while (mpg123_read(mh, buffer, buffer_size, &done) == MPG123_OK)
ao_play(a_dev, reinterpret_cast<char*>(buffer), done);
}
mpg123_handle *mh=NULL; //LESSON: cpp does not initialize pointers to NULL by default
unsigned char *buffer=NULL;
size_t buffer_size;
size_t done;
int err;
ao_device *a_dev;
const char * filename;
};
int main(int argc, char *argv[])
{
/* initializations */
ao_initialize();
ao_sample_format format;
int driver;
driver = ao_default_driver_id();
format.bits = 16;
format.rate = 44100;
format.channels = 2;
format.byte_format = AO_FMT_NATIVE;
format.matrix = 0;
ao_device *dev;
dev = ao_open_live(ao_default_driver_id(), &format, NULL);
int err = mpg123_init();
if(err != MPG123_OK) {
fprintf(stderr, "Basic setup goes wrong: %s", mpg123_plain_strerror(err));
}
std::cout << "Default constrution---->DEFAULT_CONSTRUCTOR " << std::endl;
audio_sample back_hallway; //default constructed objects that are not useable
std::cout << "Parameterized construction--->PARAM_CONSTRUCTOR" << std::endl;
audio_sample b_hallway("samples/Front_Hallway.mp3",dev); //parameterized construction, useable object
b_hallway.play();
audio_sample d_room("samples/Dining_Room.mp3",dev);
d_room.play();
audio_sample l_room("samples/Living_Room.mp3",dev);
l_room.play();
std::cout << "Useable object with useable object to be retained-->COPY ASSIGNMENT" << std::endl;
b_hallway=d_room;
b_hallway.play(); //plays
std::cout << "Useable object with useable object to be expired-->MOVE ASSIGNMENT" << std::endl;
b_hallway=std::move(d_room); //dont use d_room anymore
b_hallway.play(); //plays
std::cout << "Useable object with temporary object-->MOVE ASSIGNMENT" << std::endl;
b_hallway=audio_sample("samples/Front_Hallway.mp3",dev); //assigning a useable object with a useable temporary
b_hallway.play(); //plays
std::cout << "Nonuseable object with temporary object--->MOVE ASSIGNMENT" << std::endl;
back_hallway=audio_sample("samples/Front_Hallway.mp3",dev); //assigning a nonuseable object with a useable temporary
back_hallway.play(); //plays
std::cout << "Create object with existing object--->COPY CONSTRUCTOR" << std::endl;
audio_sample dining_room(l_room);
dining_room.play(); //plays
std::cout << "Create object with existing object to be expired--->MOVE CONSTRUCTOR" << std::endl;
audio_sample f_hall(std::move(l_room));
f_hall.play(); //plays
/* clean up */
ao_close(dev);
mpg123_exit();
ao_shutdown();
return 0;
}
| |