Skip to content

Instantly share code, notes, and snippets.

@szastupov
Created May 22, 2011 00:39
Show Gist options
  • Save szastupov/985035 to your computer and use it in GitHub Desktop.
Save szastupov/985035 to your computer and use it in GitHub Desktop.
audio experiments
#include <cassert>
#include <cstdlib>
#include <vector>
#include <boost/intrusive_ptr.hpp>
#include <AL/al.h>
#include <AL/alc.h>
#include <vorbis/vorbisfile.h>
#include "bicycles/sp.h"
#include "gfxmath/vec.h"
class ALBuffer : public RefCounted<ALBuffer> {
public:
ALBuffer();
~ALBuffer();
void setData(ALenum format, const void *data, int size, int freq);
ALuint getID() const
{
return m_id;
}
private:
ALuint m_id;
};
typedef boost::intrusive_ptr<ALBuffer> ALBufferPtr;
class ALSource {
public:
ALSource();
~ALSource();
void setBuffer(ALBufferPtr buf);
void setPosition(const vec3f &pos);
void play();
void stop();
int getState() const;
private:
ALBufferPtr m_buf;
ALuint m_id;
};
ALBuffer::ALBuffer()
{
alGenBuffers(1, &m_id);
}
ALBuffer::~ALBuffer()
{
alDeleteBuffers(1, &m_id);
}
void ALBuffer::setData(ALenum format, const void *data, int size, int freq)
{
alBufferData(m_id, format, data, size, freq);
}
ALSource::ALSource()
{
alGenSources(1, &m_id);
}
ALSource::~ALSource()
{
alDeleteSources(1, &m_id);
}
void ALSource::setBuffer(ALBufferPtr buf)
{
m_buf = buf;
if (buf)
alSourcei(m_id, AL_BUFFER, buf->getID());
}
void ALSource::setPosition(const vec3f &pos)
{
alSourcefv(m_id, AL_POSITION, pos.data());
}
void ALSource::play()
{
alSourcePlay(m_id);
}
void ALSource::stop()
{
alSourceStop(m_id);
}
int ALSource::getState() const
{
int state;
alGetSourcei(m_id, AL_SOURCE_STATE, &state);
return state;
}
void readOGG(const char *path, ALBuffer &buffer)
{
OggVorbis_File file;
int ret;
ret = ov_open(fopen(path, "r"), &file, NULL, 0);
assert(ret == 0);
ALenum format;
ALsizei freq;
vorbis_info *info = ov_info(&file, -1);
if (info->channels == 1)
format = AL_FORMAT_MONO16;
else
format = AL_FORMAT_STEREO16;
freq = info->rate;
size_t size = ov_pcm_total(&file, -1) * info->channels * 2;
std::vector<char> data;
long bytes;
int bitsream;
data.reserve(size);
do {
char tmp[1024];
bytes = ov_read(&file, tmp, sizeof(tmp), 0, 2, 1, &bitsream);
data.insert(data.end(), tmp, tmp+bytes);
} while (bytes > 0);
buffer.setData(format, &data[0], data.size(), freq);
ov_clear(&file);
}
double noteFreq(int note, int octave)
{
int e = (octave*12+note)-48;
return pow(2, (e/12.0))*261.63;
}
double getDuration(char c)
{
return 1.0/(c-'0');
}
double getNoteFreq(char c)
{
if (c == ' ')
return 0;
static const struct {
char c;
int note;
int octave;
} noteMap[] = {
{ 'D', 2, 4 },
{ 'e', 4, 4 },
{ 'f', 5, 4 },
{ 'g', 7, 4 },
{ 'a', 9, 4 },
{ 'b', 11, 4 },
{ 'c', 0, 5 },
{ 'd', 2, 5 }
};
for (size_t i = 0; i < sizeof(noteMap)/sizeof(noteMap[0]); i++)
if (noteMap[i].c == c)
return noteFreq(noteMap[i].note, noteMap[i].octave);
assert(0);
}
void parseNotes(ALBuffer &buffer, const char *notes, int rate)
{
std::vector<short> data;
while (*notes) {
double freq = getNoteFreq(*notes++);
double duration = getDuration(*notes++);
double step = M_PI*2*freq/rate;
int nsamples = duration*rate;
for (int i = 0; i < nsamples; i++)
data.push_back(20000*sin(i*step));
}
buffer.setData(AL_FORMAT_MONO16, &data[0], data.size()*2, rate);
}
int main()
{
ALCdevice *dev = alcOpenDevice(NULL);
assert(dev);
ALCcontext *ctx = alcCreateContext(dev, NULL);
assert(ctx);
alcMakeContextCurrent(ctx);
{
ALBufferPtr buffer = new ALBuffer();
//readOGG("/home/stepan/science.ogg", *buffer);
const char music[] =
"D4" "D4b4a4g4" "D2 4D4" "D4b4a4g4"
"e2 4e4" "e4c4b4a4" "f2 4d4" "d4d4c4a4"
"b2g4D4" "D4b4a4g4" "D2 4D4" "D4b4a4g4"
"e2 4e4" "e4c4b4a4" "d4d4d4d4" "e4d4c4a4"
"g2g4 4" "b4b4b2" "b4b4b2" "b4d4g4a8" "b2"
"c4c4c4c8" "c4b4b4b8b8" "b4a4a4b4" "a2d2"
"b4b4b2" "b4b4b2" "b4d4g4a8" "b2 4" "c4c4"
"c4b4b4b8b8" "d4d4c4a4" "g2";
parseNotes(*buffer, music, 44100);
ALSource source;
source.setBuffer(buffer);
source.play();
while (source.getState() != AL_STOPPED)
sleep(1);
}
alcMakeContextCurrent(NULL);
alcDestroyContext(ctx);
alcCloseDevice(dev);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment