I have to write a simple sinthesizer at university which uses sdl_mixer to generate sine waves. I got a code from my teacher which work on windows correctly, but in ubuntu it exits with segmentation fault. I installed both sdl_mixer1.2-dev and sdl1.2-dev packages. I tried a code that generates tone with sdl_audio. It worked fine, but I heard that for multi-channel playback, sdl_mixer is the solution. The getch() part of the code is working well, the problem is with the sound manager part.
Can somebody help me to solve this problem?
Here is my code:
#include <iostream>
#include <termios.h>
#include <stdio.h>
#include<cmath>
#include <SDL/SDL_mixer.h>
#include<vector>
using namespace std;
class SoundManager
{
int channelnum;
vector<Mix_Chunk*> chunks;
public:
void init()
{
if (Mix_OpenAudio(48000,AUDIO_S16, 2, 1024) == -1)
{
cerr << "audio hiba" << endl;
exit(1);
}
}
SoundManager(int asked_channelnum=64)
{
channelnum = Mix_AllocateChannels(asked_channelnum);
chunks.assign(channelnum, (Mix_Chunk*)0);
}
int get_channelnum() const
{
return channelnum;
}
void play_stereo(const vector<short int>& v, int volume=128)
{
const short int *p = &(v[0]);
// short int * p = new short int[v.size()];
// for (size_t i=0;i<v.size();i++) {
// p[i]=v[i];
// }
Mix_Chunk * ownsample = new Mix_Chunk;
ownsample->alen = v.size()*2;
ownsample->abuf = (Uint8*)p;
ownsample->allocated = 1;
ownsample->volume = volume;
int playchannel = Mix_PlayChannel(-1, ownsample, 0);
if (playchannel != -1 && chunks[playchannel])
{
delete[] chunks[playchannel]->abuf;
Mix_FreeChunk(chunks[playchannel]);
}
if (playchannel != -1)
chunks[playchannel] = ownsample;
}
};
Mix_Chunk *ownsample = 0;
Mix_Chunk *samples = 0;
void hang()
{
if (Mix_OpenAudio(48000,AUDIO_S16, 2, 1024) == -1)
{
cerr << "audio hiba" << endl;
exit(1);
}
vector<short> s(48000*2,0);
for (int i=0; i<s.size()/2; i++)
{
s[i*2] = sin(i/10.0+i*i/10000.0)*32000*(1/sqrt(i/100.0));
s[i*2+1] = sin(i/10.0)*32000*(1/sqrt(i/100.0));
}
samples = Mix_LoadWAV("ding.wav");
ownsample = new Mix_Chunk;
ownsample->alen = s.size()*2;
ownsample->abuf =(unsigned char*) &(s[0]);
ownsample->allocated = 0;
ownsample->volume = 128;
cout << samples->alen << endl;
if (!samples)
{
cerr << "wav 'ding.wav' open error" << endl;
exit(1);
}
int channelnum = Mix_AllocateChannels(64);
if (channelnum != 64)
{
cerr << "warning: not as many channels are reserved as attended"<<endl;
}
if (Mix_PlayChannel(-1, ownsample, 0)==-1 )
{
cerr << "error on play" << endl;
}
// if (Mix_PlayChannel(-1, samples, 0)==-1 ) {
// cerr << "error on play" << endl;
// }
}
void pitty(SoundManager &sm)
{
vector<short> s(48000*2,0);
for (int i=0; i<s.size()/2; i++)
{
s[i*2] = sin(i/10.0+i*i/10000.0)*32000*(1/sqrt(i/100.0));
s[i*2+1] = sin(i/10.0)*32000*(1/sqrt(i/100.0));
}
sm.play_stereo(s);
}
static struct termios old, New;
/* Initialize New terminal i/o settings */
void initTermios(int echo)
{
tcgetattr(0, &old); /* grab old terminal i/o settings */
New = old; /* make New settings same as old settings */
New.c_lflag &= ~ICANON; /* disable buffered i/o */
New.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */
tcsetattr(0, TCSANOW, &New); /* use these New terminal i/o settings now */
}
/* Restore old terminal i/o settings */
void resetTermios(void)
{
tcsetattr(0, TCSANOW, &old);
}
/* Read 1 character - echo defines echo mode */
char getch_(int echo)
{
int ch;
initTermios(echo);
ch = getchar();
resetTermios();
return ch;
}
/* Read 1 character without echo */
int getch(void)
{
return getch_(o);
}
/* Read 1 character with echo */
int getche(void)
{
return getch_(1);
}
int main(void)
{
SoundManager sm(16);
sm.init();
vector<short> s(48000*2,0);
for (int i=0; i<s.size()/2; i++)
{
s[i*2] = sin(i/10.0+i*i/10000.0)*32000*(1/sqrt(i/100.0));
s[i*2+1] = sin(i/10.0)*32000*(1/sqrt(i/100.0));
}
int c;
while (1)
{
c = getch();
cout <<"keycode:\n";
cout <<c;
sm.play_stereo(s);
}
return 0;
}
Thank you for your help in advance.
Greetings, Istvan Velegi
This looks absolutely, totally bogus:
Yes, I realize
chunks[playchannel]
isn'townsample
yet, but you do putownsample
into thechunks
queue, so eventually you will come back around and try todelete[]
the internal array storage of avector<short int>
.That's very bad.
This commented-out code actually seems to be the correct thing to have in place of
const short int *p = &(v[0])
: