генерация тона с помощью sdl_mixer завершается с ошибкой сегментации в ubuntu 12.04 64 bit

0

Я должен написать простой синтезатор в университете, который использует sdl_mixer для генерации синусоидальных волн. У меня есть код от моего учителя, который работает над окнами правильно, но в ubuntu он выходит с ошибкой сегментации. Я установил оба пакета sdl_mixer1.2-dev и sdl1.2-dev. Я пробовал код, который генерирует тон с помощью sdl_audio. Он работал отлично, но я слышал, что для многоканального воспроизведения решение sdl_mixer является решением. Часть кода getch() работает хорошо, проблема связана с частью звукового менеджера.

Может ли кто-нибудь помочь мне решить эту проблему?

Вот мой код:

#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;
}

Благодарим вас за помощь.

Приветствую, Иштван Велеги

  • 0
    Вау, это горячий беспорядок Вы могли бы попытаться четко отформатировать код, а затем показать нам, куда вы преследовали ошибку сегментации (то есть то, что приведенный выше вызов или разыменование указателя фактически вызывает ошибку). Также, если вы запускаете это в отладчике, таком как GDB, покажите нам, где вы застряли, пытаясь интерпретировать то, что вы видите.
  • 0
    Вы имеете в виду форматировать код здесь на форуме или перед публикацией? Я не использовал форматирование кода, потому что, поскольку я не вижу, что на экране, мне это раньше не было нужно. Можно ли публиковать здесь информацию об отладке с помощью valgrind?
Показать ещё 2 комментария
Теги:
ubuntu-12.04
sdl-mixer

2 ответа

0

Это выглядит абсолютно, абсолютно фиктивным:

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;

Да, я понимаю, что chunks[playchannel] еще не ownsample, но вы помещаете ownsample в очередь chunks, поэтому в итоге вы вернетесь и попытаетесь delete[] внутреннюю память массива vector<short int>.

Это очень плохо.

Этот прокомментированный код на самом деле кажется правильным, если вместо 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

(1) если вы получаете ошибку сегментации, вы можете перекомпилировать код с помощью отладочных символов (если вы используете g++ или клан g++); используйте -g3.

(2) запустить программу с помощью отладчика и получить трассировку стека, где происходит сегментация кода (используйте gdb).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню