tone generation with sdl_mixer exits with segmentation fault in ubuntu 12.04 64 bit

603 views Asked by At

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

2

There are 2 answers

0
Joe Z On

This looks absolutely, totally bogus:

void play_stereo(const vector<short int>& v, int volume=128)
{
    const short int *p = &(v[0]);

    //...

    ownsample->abuf = (Uint8*)p;

    //...
        delete[] chunks[playchannel]->abuf;

Yes, I realize chunks[playchannel] isn't ownsample yet, but you do put ownsample into the chunks queue, so eventually you will come back around and try to delete[] the internal array storage of a vector<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]):

//        short int * p = new short int[v.size()];
//        for (size_t i=0;i<v.size();i++) {
//            p[i]=v[i];
//        }
0
kingtorus On

(1) if you are getting a segmentation fault can you recompile the code with debugging symbols on (if you are using g++ or clang++); use -g3.

(2) run the program using a debugger and get a stack trace of where the code segmentation faults (use gdb).