1

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

  • Wow, that's a hot mess. You might try formatting the code clearly, and then show us where you've chased the segmentation fault to (ie. what call or pointer-dereference above actually triggers the fault). Also, if you've run this in a debugger, such as GDB, show us where you've gotten stuck trying to interpret what you're seeing. – Joe Z Dec 01 '13 at 17:23
  • Do you mean format the code here in the forum or before posting? I haven't used code formatting because as I don't see what is on the screen it wasn't necessary for me before. Is it okay if I post here the debugging information with valgrind? – user3054779 Dec 01 '13 at 17:43
  • I see what you are talking about. The code is totally wrong. Mabe the forum reformatted it. I will ask a friend who can correct this mistake. – user3054779 Dec 01 '13 at 17:53
  • Once you have the code formatted so we can read it, also show us exactly how far you've gotten narrowing down the segfault. (For example, which function faults, what its arguments are, etc.) If you can remove code from the example and have it still fail, that's even better. You might check out http://sscce.org/ for hints how to cut your code down to a small, self-contained example. – Joe Z Dec 01 '13 at 18:00

2 Answers2

0

(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).

kingtorus
  • 953
  • 12
  • 15
0

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];
//        }
Joe Z
  • 17,413
  • 3
  • 28
  • 39