This repository has been archived on 2022-12-02. You can view files and clone it, but cannot push or open issues or pull requests.
Wavehpp/wave.hpp

323 lines
9.8 KiB
C++
Raw Normal View History

2019-11-08 17:54:18 +00:00
//////////////////////////////////////////////////////////////////////////
//wave.hpp
//load a .wav file into memeory and play at will
//MUST ADD winmm TO YOUR LINKER SETTINGS ELSE THIS WILL NOT WORK
//
//Free to use, modify, publish, etc.
//if you're feeling nice, mention me :D
//
//////////////////////////////////////////////////////////
//Date: 11-5-19 //
//Author: Tyler Perkins //
//Pseudonym: Clortox //
//modified from the code provided by: //
//Chervil on the c++ fourms //
//Use with care :) //
//////////////////////////////////////////////////////////
//Interface: //
//wave::Wave(std::string) provide file path to a //
// .wav file, else will be //
// empty //
//------------------------------------------------------//
//wave::isOk() returns weather the wav //
// is ready to be played, //
// like ifstream::good() //
//------------------------------------------------------//
//wave::play(bool) plays wave file, will not//
// if !isOk().bool is async //
// async=true,pause and play//
// async=false,open new //
// thread to play on //
//------------------------------------------------------//
//wave::resign(std::string) load new wav file into //
// memory //
//------------------------------------------------------//
//wave::dumpbuffer() returns a string with //
// the file buffer in it //
// really only for debug //
//------------------------------------------------------//
//wave::isWave(std::string) returns true if is wave //
// file, checks magic bytes //
//////////////////////////////////////////////////////////
#ifndef _WAVE_HPP_
#define _WAVE_HPP_
#include <windows.h>
#include <new>
#include <fstream>
#include <sstream>
#include <utility>
class wave{
public:
wave (); //def ctor
wave (std::string&); //ctor with path
//rule of three
wave (const wave&); //copy ctor
~wave (); //dtor
wave& operator= (wave&); //assignment operator
void swap (wave&); //swap
bool isOk () const; //check if ready to run
void play (bool); //play loaded file
void resign (std::string&); //load new file into memory
////DEBUG////
std::string dumpbuffer() const; //send back the buffer in a string
private:
bool isWave(std::string&) const; //check if file is a wave file via magic bytes
char *buffer;
HINSTANCE HInstance;
bool isok;
int buffsize;
};
/////////////////////////////////////////////////
//defualt ctor (WORKS)
//will set everything to blank so it is ready to role
wave::wave(){
isok = false;
buffer = 0;
buffsize = 0;
}
/////////////////////////////////////////////////
//preffered ctor the user use (WORKS)
//will just load file into memory, throw error if not working
wave::wave(std::string &path){
isok = false;
try{
if(path == ""){
throw 15;
}
std::ifstream infile(path.c_str());
if(!infile.good()){
throw 10;
}
if(!isWave(path)){
throw 20;
}
}
catch(int e){
if(e == 10){
std::cerr << "wave::wave(std::string&); file either was moved or does not exist\nEXITING\n";
return;
}
if(e == 15){
std::cerr << "wave::wave(std::string&); file either was moved or does not exist\nEXITING\n";
return;
}
if(e == 20){
std::cerr << "wave::wave(std::string&); file is not a .wav file\nEXITING\n";
return;
}
}
buffer = 0;
HInstance = GetModuleHandle(0);
std::ifstream infile(path,std::ios::binary);
infile.seekg(0,std::ios::end);
buffsize = infile.tellg();
buffer = new char[buffsize];
infile.seekg(0,std::ios::beg);
infile.read(buffer,buffsize);
infile.close();
isok = true;
}
/////////////////////////////////////////////////
//copy ctor (WORKS)
//just moves copies the buffer over
wave::wave(const wave &rhs){
isok = false;
HInstance = rhs.HInstance;
buffsize = rhs.buffsize;
buffer = new char[buffsize]; //the point of this is so that if the other wave goes out of scope,
//this one is still useable
for(int i=0;i<=buffsize-1;i++){ //copy data over
buffer[i] = rhs.buffer[i];
}
isok = rhs.isOk();
}
/////////////////////////////////////////////////
//dtor (WORKS)
//just dealloc the buffer
wave::~wave(){
PlaySound(NULL,0,0); //stop the sound
delete[] buffer;
}
/////////////////////////////////////////////////
//assignment operator (WORKS)
//
wave& wave::operator=(wave &rhs){
swap(rhs);
return *this;
}
/////////////////////////////////////////////////
//swap func (WORKS)
//swaps all the private elements
void wave::swap(wave &rhs){
char* temp = rhs.buffer;
rhs.buffer = buffer;
buffer = temp;
int tempbuf = rhs.buffsize;
rhs.buffsize = buffsize;
buffsize = tempbuf;
bool tempok = rhs.isok;
rhs.isok = isok;
isok = tempok;
HINSTANCE tempinst = rhs.HInstance;
rhs.HInstance = HInstance;
HInstance = tempinst;
return;
}
/////////////////////////////////////////////////
//returns isok (WORKS)
//useful for checking if the file is working
bool wave::isOk() const{
return isok;
}
/////////////////////////////////////////////////
//the star of the show (WORKS)
//play the file using winapi
void wave::play(bool async){
try{
if(!isOk()){
throw 12;
}
}
catch(int e){
if(e == 12){
std::cerr << "wave::play(bool); cannot play file\nEXITING\n";
return;
}
}
if(async){
PlaySound(buffer, HInstance, SND_MEMORY | SND_ASYNC);
}else{
PlaySound(buffer, HInstance, SND_MEMORY);
}
return;
}
/////////////////////////////////////////////////
//almost the std::string ctor but not quite
//just load a new path into memory
void wave::resign(std::string &path){
isok = false;
try{
std::ifstream infile(path.c_str());
if(!infile.good()){
throw 10;
}
if(!isWave(path)){
throw 19;
}
}
catch(int e){
if(e == 10){
std::cerr << "wave::resign(std::string&); file either was moved or does not exist\nEXITING\n";
return;
}
if(e == 19){
std::cerr << "wave::resign(std::string&); file is not a .wav file\nEXITING\n";
return;
}
}
delete[] buffer;
buffer = 0;
buffsize = 0;
HInstance = GetModuleHandle(0);
std::ifstream infile(path,std::ios::binary);
infile.seekg(0,std::ios::end);
buffsize = infile.tellg();
buffer = new char[buffsize];
infile.seekg(0,std::ios::beg);
infile.read(buffer,buffsize);
infile.close();
isok = true;
return;
}
/////////////////////////////////////////////////
//send back a string with everything in it
//expect a lot of garbage
std::string wave::dumpbuffer() const{
std::string resultant;
for(int i=0;i<=buffsize-1;i++){
resultant += buffer[i];
}
return resultant;
}
/////////////////////////////////////////////////
//check if the file is a wav file
//below is the definition of the magic bytes
bool wave::isWave(std::string &path) const{
try{
if(path == ""){
throw 18;
}
std::ifstream infile(path.c_str());
if(!infile.good()){
throw 16;
}
}
catch(int e){
if(e == 16){
std::cerr << "wave::isWave(std::string&); file either was moved or does not exist\nEXITING\n";
return false;
}
if(e == 18){
std::cerr << "wave::isWave(std::string&); path is empty!\nEXITING\n";
return false;
}
}
std::ifstream infile(path.c_str(),std::ios_base::binary);
char ch;
std::string temp = "";
std::cout << "wav head: " << std::endl;
for(int i=0;i<=11;i++){
infile.get(ch);
temp += ch;
}
try{
std::string first = "RIFF"; //i know these are magic numbers,
std::string last = "WAVE"; //but these are standards, theyre not changing
//or i hope so
if(!(temp.substr(0,4) == first)){
throw 17;
}
if(!(temp.substr(8,4) == last)){
throw 17;
}
}
catch(int e){
if(e == 17){
std::cout << "wave::isWave(std::string&); file is not formatted as a .wav\nEXITING\n";
return false;
}
}
return true;
}
#endif // _WAVE_HPP_