Назначение локальных переменных приводит к остановке обработки аудио в JUCE.

EDIT: оказалось, что это неинициализированная переменная, создающая хаотичное поведение. См. эту публикацию о получении дополнительных предупреждений компилятора для JUCE.

Я пытался создать базовый синтезатор и быстро столкнулся с абсурдной проблемой, когда просто пытался присвоить значение вновь объявленной переменной. После изучения простого учебника по синусоидальному синтезу JUCE я столкнулся с проблемой. Это основной код моей функции getNextAudioBlock(), когда она создает белый шум. Обратите внимание, что четыре целых числа объявлены и назначены повсюду:

const int numChannels = bufferToFill.buffer->getNumChannels();
const int numSamples = bufferToFill.numSamples;
for (int channel = 0; channel < numChannels; channel++){
    float* const buffer = bufferToFill.buffer -> getWritePointer(channel, bufferToFill.startSample);
    for (int sample; sample < numSamples; sample++){
        buffer[sample] = (randomGen.nextFloat() * 2.0f - 1.0f);
    }
}

Однако, как только я пытаюсь добавить еще один int, я больше не получаю звука. Просто добавьте строку int unusedVariable = 0; в любом месте функции getNextAudioBlock(), но до того, как присваивание buffer[sample] немедленно вернется из функции, и поэтому оно не производит звука.

Если я просто объявлю новую переменную (int unusedVariable;), она все равно будет работать. Только конкретно часть присваивания вызывает ошибку. Кроме того, если я объявлю переменную глобальным членом, то назначение внутри функции будет работать нормально.

Повторюсь, это работает:

buffer[sample] = (randomGen.nextFloat() * 2.0f - 1.0f;

Это работает:

int unusedVariable;
buffer[sample] = (randomGen.nextFloat() * 2.0f - 1.0f;

Но это не так:

int unusedVariable = 0;
buffer[sample] = (randomGen.nextFloat() * 2.0f - 1.0f;

Моя единственная идея заключалась в том, что выделение новой памяти в потоке аудио вызывает ошибку, но я видел объявление и назначение, выполненное в других онлайн-источниках и даже в моей точно такой же функции с numChannels, numSamples, каналом и семплом, все они выделены и назначены просто отлично. Я также подумал, что это как-то связано с использованием класса Random, но у меня возникает та же проблема, даже когда он генерирует синусоидальные волны.

РЕДАКТИРОВАТЬ: Вот точный код, скопированный из проекта. Прямо здесь nextSample объявлен глобально, так как буфер не заполняется, когда он объявлен локально

  void MainContentComponent::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
  {
    const int numChannels = bufferToFill.buffer->getNumChannels();
    const int numSamples = bufferToFill.numSamples;
    for (int channel = 0; channel < numChannels; channel++){
        float* const buffer = bufferToFill.buffer -> getWritePointer (channel, bufferToFill.startSample);
        for (int sample; sample < numSamples; sample++){
            // nextSample = (randomGen.nextFloat() * 2.0f - 1.0f); // For Randomly generated White Noise
            nextSample = (float) std::sin (currentAngle);
            currentAngle += angleDelta;
            buffer[sample] = nextSample * volumeLevel;
        }
    }
  }

person brenthompson2    schedule 20.08.2017    source источник
comment
Вероятно, это не решение вашей проблемы, но предназначено ли условие numChannels в for (int channel = 0; numChannels; channel++)? Это, скорее всего, приведет к бесконечному циклу.   -  person Stephan Lechner    schedule 21.08.2017
comment
извините, мой исходный код правильно говорит (...; канал ‹ numChannels;...)   -  person brenthompson2    schedule 21.08.2017
comment
Пожалуйста, вставьте настоящий код здесь. buffer[sample] = (randomGen.nextFloat() * 2.0f - 1.0f; даже не скомпилируется из-за отсутствия закрытия ). Или фактически предоставьте mcve.   -  person user7860670    schedule 21.08.2017
comment
Я добавил точный код, а также связал его с FirstSynth и AdditiveManual, двумя проектами, которые работают только тогда, когда переменные являются глобальными членами.   -  person brenthompson2    schedule 21.08.2017
comment
@brenthompson2 - если вы являетесь платным лицензиатом и живая сборка у вас не работает, вы должны опубликовать сообщение на форуме JUCE forum.juce.com, за которым следит команда разработчиков JUCE.   -  person bgporter    schedule 26.08.2017


Ответы (1)


Я создал новый проект AudioApplication в Projucer и вставил этот блок кода в метод getNextAudioBlock() (добавляя разумные переменные-члены, поскольку вы ссылаетесь на них здесь).

Компилятор сразу указал на проблему — переменная цикла sample ниже не инициализирована (и C++ не инициализирует ее по умолчанию), поэтому, если память, используемая этой переменной, содержала значение, меньшее размер буфера, вы будете генерировать звук; в противном случае буфер, переданный в эту функцию, не затрагивается, потому что цикл никогда не запускается.

    for (int sample; sample < numSamples; sample++){
        nextSample = (randomGen.nextFloat() * 2.0f - 1.0f); // For Randomly generated White Noise
        //nextSample = (float) std::sin (currentAngle);
        //currentAngle += angleDelta;
        buffer[sample] = nextSample * volumeLevel;
    }

посмотрите, не исправит ли это изменение на for (int sample=0; ситуацию для вас.

person bgporter    schedule 24.08.2017
comment
Большое Вам спасибо. Это имеет большой смысл. Я попробую это утром. Какой компилятор вы использовали? - person brenthompson2; 25.08.2017
comment
Xcode 8, но я ожидаю, что поведение здесь будет везде одинаково непредсказуемым - см. этот ответ SO: stackoverflow.com/questions/1597405/ - person bgporter; 25.08.2017
comment
Это было решением. Это также решило мою проблему, когда звук не выводился на оба канала. Теперь, если только я смогу понять, как скомпилировать эти предупреждения на моем компьютере с Ubuntu. .. - person brenthompson2; 26.08.2017