Аудио - Сборка /генерация и воспроизведение чистого сигнала

РЕДАКТИРОВАТЬ после ответа Бена

Я пытаюсь сделать что-то, что должно быть очень легко для кого-то, кто используется с обработкой сигналов, но это доставляет мне головную боль. Я просто пытаюсь сгенерировать звуковой сигнал, который будет воспроизводиться произвольное количество секунд, может быть меньше или больше секунды (0,1 с, 0,88 с, 1,2 с, ...).

Для генерации звукового сигнала я использую этот хорошо известный метод:

+ (NSData*) WAVSoundForFrequency:(float)frequency duration:(float)seconds sampleRate:(unsigned int)sampleRate gain:(float)gain
{
    int frames = seconds * sampleRate;
    float* rawSound = (float*)malloc(frames*sizeof(float));
    if (rawSound == NULL) return nil;

    for (int i = 0; i < frames; i++)
      rawSound[i] = gain * sinf(i*2*M_PI*frequency/sampleRate);

    // converting to raw sound and returning the whole thing
}

Это называется в основном с:

AVAudioPlayer* player = [self.audioPlayerManager buildSoundFrequency:200 duration:0.18 sampleRate:44100 gain:1.0];
player.volume = 1.0;
player.numberOfLoops = -1;
[player play];

Проблема в том, что с этими параметрами волна в конце кажется не завершенной, поэтому она генерирует щелчки, которые можно услышать в каждом цикле. Но не нажимайте, если я использую 0,5 секунды или 1,0 секунды для длительности и 200 герц (используя скорректированную длительность курса). Тем не менее, для целей тестирования, если я использую 400 герц или 440 герц вместо 200, у меня теперь есть клики с 0,5 с.

Обратите внимание, что этот цикл предназначен только для тестирования и определения, есть ли щелчки или нет. В конце концов, звук должен воспроизводиться только в желаемое время.

Я догадался, что это из-за длительности, не равной кратному циклу волны, поэтому я настроил вызов таким образом, чтобы скорректировать требуемую длительность до ближайшей длительности, кратной одному циклу в требуемая частота:

float wantedDuration = 0.18;
float hertz = 200;
int wantedSampleRate = 44100;

// Adjusting wanted duration so the duration contains an entiere number of waves
float oneWaveDurationInSeconds = 1.0/hertz;
int nbWavesNeeded = roundf(wantedDuration/oneWaveDurationInSeconds);
float adjustedDuration = nbWavesNeeded * oneWaveDurationInSeconds;

// Adjusting sample rate so one wave takes an entiere number of samples
float oneSampleDuration = 1.0/wantedSampleRate;

int adjustedSamplerate = wantedSampleRate;
while (YES) {
    oneSampleDuration = 1.0/adjustedSamplerate;
    if (roundf(oneWaveDurationInSeconds/oneSampleDuration) == oneWaveDurationInSeconds/oneSampleDuration) break;
    adjustedSamplerate++;
    NSLog(@"%d", adjustedSamplerate);
}

// Debug
float nbSamplesForOneWave = oneWaveDurationInSeconds / (1.0/adjustedSamplerate);
NSLog(@"nbSamplesForOneWave : %f", nbSamplesForOneWave);

// Execute
MyAudioPlayer* player = [self.manager preloadSoundFrequency:hertz duration:adjustedDuration sampleRate:adjustedSamplerate gain:1.0 
                                                 identifier:@"ii" category:@"Radar"];
player.volume = 1.0;
player.numberOfLoops = -1;
[player play];

Но щелчок еще есть.

Мне сказали, что проблема может быть в частоте дискретизации. Но я действительно не понимаю, почему. Насколько я понял, частота дискретизации - это количество выборок, определенных за одну секунду. Так что для меня это не зависит ни от длительности, ни от частоты.
И ... Почему у меня не должно быть звука 0,18 с качеством семпла 44100 ...

Но в любом случае ... Я предполагал, что если я выберу 44100 точек за одну секунду, запрос продолжительности 0,18 должен привести к 44100 * 0,18 выборкам. Это число, представленное как int frames. Поэтому я попытался заменить

      rawSound[i] = gain * sinf(i*2*M_PI*frequency/sampleRate);

с

      rawSound[i] = gain * sinf(i*2*M_PI*frequency/frames);

Это не работает, это только делает звук намного более острым. И я до сих пор не понимаю, почему. Я думаю, что это будет менее качественный звук, так как там будет меньше образцов.

Может ли кто-нибудь помочь мне сгенерировать этот (возможно, петлевой) звуковой сигнал для любой требуемой задержки с желаемым качеством и частотой?

Я уверен, что это звучит (:-)) легко, но я не вижу пути для достижения этой цели.

Я попытался поставить NSLog, чтобы увидеть используемые значения (журнал без рамп Пола):

    if (i<20 || i > frames-20) NSLog(@"%f", rawSound[i]);

Для 440 Гц, частота дискретизации 44100, длительность 1,0 (без регулировки): Нет клика

2011-10-31 01:02:34.110 testAudio[9602:207] 0.000000
2011-10-31 01:02:34.112 testAudio[9602:207] 0.062648
2011-10-31 01:02:34.113 testAudio[9602:207] 0.125051
2011-10-31 01:02:34.114 testAudio[9602:207] 0.186961
2011-10-31 01:02:34.115 testAudio[9602:207] 0.248138
2011-10-31 01:02:34.116 testAudio[9602:207] 0.308339
2011-10-31 01:02:34.116 testAudio[9602:207] 0.367330
2011-10-31 01:02:34.117 testAudio[9602:207] 0.424877
2011-10-31 01:02:34.117 testAudio[9602:207] 0.480755
2011-10-31 01:02:34.118 testAudio[9602:207] 0.534744
2011-10-31 01:02:34.119 testAudio[9602:207] 0.586632
2011-10-31 01:02:34.121 testAudio[9602:207] 0.636216
2011-10-31 01:02:34.121 testAudio[9602:207] 0.683300
2011-10-31 01:02:34.122 testAudio[9602:207] 0.727699
2011-10-31 01:02:34.123 testAudio[9602:207] 0.769240
2011-10-31 01:02:34.123 testAudio[9602:207] 0.807759
2011-10-31 01:02:34.124 testAudio[9602:207] 0.843104
2011-10-31 01:02:34.125 testAudio[9602:207] 0.875137
2011-10-31 01:02:34.126 testAudio[9602:207] 0.903732
2011-10-31 01:02:34.127 testAudio[9602:207] 0.928777
2011-10-31 01:02:34.130 testAudio[9602:207] -0.928790
2011-10-31 01:02:34.130 testAudio[9602:207] -0.903724
2011-10-31 01:02:34.131 testAudio[9602:207] -0.875102
2011-10-31 01:02:34.132 testAudio[9602:207] -0.843167
2011-10-31 01:02:34.132 testAudio[9602:207] -0.807795
2011-10-31 01:02:34.133 testAudio[9602:207] -0.769245
2011-10-31 01:02:34.134 testAudio[9602:207] -0.727667
2011-10-31 01:02:34.135 testAudio[9602:207] -0.683225
2011-10-31 01:02:34.135 testAudio[9602:207] -0.636283
2011-10-31 01:02:34.136 testAudio[9602:207] -0.586658
2011-10-31 01:02:34.137 testAudio[9602:207] -0.534724
2011-10-31 01:02:34.138 testAudio[9602:207] -0.480687
2011-10-31 01:02:34.138 testAudio[9602:207] -0.424978
2011-10-31 01:02:34.139 testAudio[9602:207] -0.367383
2011-10-31 01:02:34.140 testAudio[9602:207] -0.308342
2011-10-31 01:02:34.140 testAudio[9602:207] -0.248087
2011-10-31 01:02:34.141 testAudio[9602:207] -0.186856
2011-10-31 01:02:34.142 testAudio[9602:207] -0.125132
2011-10-31 01:02:34.142 testAudio[9602:207] -0.062676

Для 440 Гц, частота дискретизации 44100, длительность 0,5 (без регулировки): Нет клика

2011-10-31 01:04:51.043 testAudio[9714:207] 0.000000
2011-10-31 01:04:51.045 testAudio[9714:207] 0.062648
2011-10-31 01:04:51.047 testAudio[9714:207] 0.125051
2011-10-31 01:04:51.049 testAudio[9714:207] 0.186961
2011-10-31 01:04:51.049 testAudio[9714:207] 0.248138
2011-10-31 01:04:51.050 testAudio[9714:207] 0.308339
2011-10-31 01:04:51.051 testAudio[9714:207] 0.367330
2011-10-31 01:04:51.052 testAudio[9714:207] 0.424877
2011-10-31 01:04:51.053 testAudio[9714:207] 0.480755
2011-10-31 01:04:51.054 testAudio[9714:207] 0.534744
2011-10-31 01:04:51.055 testAudio[9714:207] 0.586632
2011-10-31 01:04:51.055 testAudio[9714:207] 0.636216
2011-10-31 01:04:51.056 testAudio[9714:207] 0.683300
2011-10-31 01:04:51.057 testAudio[9714:207] 0.727699
2011-10-31 01:04:51.059 testAudio[9714:207] 0.769240
2011-10-31 01:04:51.060 testAudio[9714:207] 0.807759
2011-10-31 01:04:51.060 testAudio[9714:207] 0.843104
2011-10-31 01:04:51.061 testAudio[9714:207] 0.875137
2011-10-31 01:04:51.062 testAudio[9714:207] 0.903732
2011-10-31 01:04:51.062 testAudio[9714:207] 0.928777
2011-10-31 01:04:51.064 testAudio[9714:207] -0.928795
2011-10-31 01:04:51.065 testAudio[9714:207] -0.903730
2011-10-31 01:04:51.065 testAudio[9714:207] -0.875109
2011-10-31 01:04:51.066 testAudio[9714:207] -0.843109
2011-10-31 01:04:51.067 testAudio[9714:207] -0.807731
2011-10-31 01:04:51.067 testAudio[9714:207] -0.769253
2011-10-31 01:04:51.068 testAudio[9714:207] -0.727676
2011-10-31 01:04:51.069 testAudio[9714:207] -0.683324
2011-10-31 01:04:51.070 testAudio[9714:207] -0.636199
2011-10-31 01:04:51.070 testAudio[9714:207] -0.586669
2011-10-31 01:04:51.071 testAudio[9714:207] -0.534736
2011-10-31 01:04:51.072 testAudio[9714:207] -0.480806
2011-10-31 01:04:51.072 testAudio[9714:207] -0.424880
2011-10-31 01:04:51.073 testAudio[9714:207] -0.367282
2011-10-31 01:04:51.074 testAudio[9714:207] -0.308355
2011-10-31 01:04:51.074 testAudio[9714:207] -0.248100
2011-10-31 01:04:51.075 testAudio[9714:207] -0.186989
2011-10-31 01:04:51.076 testAudio[9714:207] -0.125025
2011-10-31 01:04:51.077 testAudio[9714:207] -0.062689

Для 440 Гц, частота дискретизации 44100, длительность 0,25 (без регулировки): Жесткие клики

2011-10-31 01:05:25.245 testAudio[9759:207] 0.000000
2011-10-31 01:05:25.247 testAudio[9759:207] 0.062648
2011-10-31 01:05:25.249 testAudio[9759:207] 0.125051
2011-10-31 01:05:25.250 testAudio[9759:207] 0.186961
2011-10-31 01:05:25.251 testAudio[9759:207] 0.248138
2011-10-31 01:05:25.252 testAudio[9759:207] 0.308339
2011-10-31 01:05:25.252 testAudio[9759:207] 0.367330
2011-10-31 01:05:25.253 testAudio[9759:207] 0.424877
2011-10-31 01:05:25.254 testAudio[9759:207] 0.480755
2011-10-31 01:05:25.254 testAudio[9759:207] 0.534744
2011-10-31 01:05:25.255 testAudio[9759:207] 0.586632
2011-10-31 01:05:25.256 testAudio[9759:207] 0.636216
2011-10-31 01:05:25.257 testAudio[9759:207] 0.683300
2011-10-31 01:05:25.257 testAudio[9759:207] 0.727699
2011-10-31 01:05:25.258 testAudio[9759:207] 0.769240
2011-10-31 01:05:25.259 testAudio[9759:207] 0.807759
2011-10-31 01:05:25.260 testAudio[9759:207] 0.843104
2011-10-31 01:05:25.261 testAudio[9759:207] 0.875137
2011-10-31 01:05:25.261 testAudio[9759:207] 0.903732
2011-10-31 01:05:25.262 testAudio[9759:207] 0.928777
2011-10-31 01:05:25.263 testAudio[9759:207] -0.928781
2011-10-31 01:05:25.264 testAudio[9759:207] -0.903727
2011-10-31 01:05:25.264 testAudio[9759:207] -0.875135
2011-10-31 01:05:25.265 testAudio[9759:207] -0.843105
2011-10-31 01:05:25.266 testAudio[9759:207] -0.807763
2011-10-31 01:05:25.267 testAudio[9759:207] -0.769249
2011-10-31 01:05:25.267 testAudio[9759:207] -0.727692
2011-10-31 01:05:25.268 testAudio[9759:207] -0.683296
2011-10-31 01:05:25.269 testAudio[9759:207] -0.636217
2011-10-31 01:05:25.269 testAudio[9759:207] -0.586638
2011-10-31 01:05:25.270 testAudio[9759:207] -0.534756
2011-10-31 01:05:25.271 testAudio[9759:207] -0.480746
2011-10-31 01:05:25.271 testAudio[9759:207] -0.424873
2011-10-31 01:05:25.272 testAudio[9759:207] -0.367332
2011-10-31 01:05:25.273 testAudio[9759:207] -0.308348
2011-10-31 01:05:25.273 testAudio[9759:207] -0.248152
2011-10-31 01:05:25.274 testAudio[9759:207] -0.186952
2011-10-31 01:05:25.275 testAudio[9759:207] -0.125047
2011-10-31 01:05:25.276 testAudio[9759:207] -0.062652

ИЗМЕНИТЬ

Я записал сгенерированный образец звука (440 Гц, 444100 сэмплов, 0,1 секунды) в файл и открыл его с помощью редактора звука. Вырезайте и вставляйте звук много раз, чтобы сделать его более длинным: он воспроизводится без щелчка. Один и тот же образец звука, воспроизводимый через AVAudioPlayer, генерирует щелчки в конце каждого образца. Таким образом, проблема, похоже, заключается в AVAudioPlayer, по причине, которую я не понимаю, потому что только некоторые конкретные значения генерируют эти клики.

ИЗМЕНИТЬ

Я использовал сгенерированный файл wav и заставил его проигрываться с помощью AVAudioPlayer с циклом: клики
Я использовал тот же файл и заставил его проигрывать цикл с OpenAL, используя пользовательскую библиотеку: больше никаких кликов. Проблема в том, что OpenAL - настоящий кошмар для понимания, и он приведет к полной переписке моей звуковой части, просто для этого плохого звука.

Проблема, очевидно, заключается в использовании AVAudioPlayer. Если у вас есть решение заставить его работать, это сэкономит мне время.

4 голоса | спросил Oliver 30 +04002011-10-30T06:37:30+04:00312011bEurope/MoscowSun, 30 Oct 2011 06:37:30 +0400 2011, 06:37:30

4 ответа


0

В общем случае к любому синтезированному звуку, который вы хотите воспроизвести, необходимо применять линейное изменение смещения (aka attack и decay ), в противном случае вы получите переходные процессы на начало и конец звука, который может быть слышен как щелчки.

Для устранения этого обычно достаточно простого линейного линейного изменения в течение нескольких мс, хотя обычно предпочтительнее использовать более плавную форму, такую ​​как экспоненциальный или приподнятый косинус.

Дополнительным бонусом является то, что вам не нужно следить за тем, чтобы ваша форма волны начиналась и заканчивалась в нуле, поскольку об этом заботятся функция начала и смещения.

const int kAttack = (int)(0.005f * sampleRate); // 5 ms attack period (samples)
const int kDecay = (int)(0.010f * sampleRate);  // 10 ms decay period (samples)

for (int i = 0; i < frames; i++)
{
    float a = gain * sinf((float)i * 2.0f * M_PI * frequency / sampleRate);
    if (i < kAttack)                // if in attack (onset) period
    {
        a *= (float)i / kAttack;    // apply linear onset ramp
    }
    else if (i > frames - kDecay)  // if in decay (offset) period
    {
        a *= 1.0f - (float)(i - (frames - kDecay)) / kDecay;   // apply linear offset ramp
    }           

    rawSound[i] = a;
}
ответил Paul R 31 +04002011-10-31T02:43:58+04:00312011bEurope/MoscowMon, 31 Oct 2011 02:43:58 +0400 2011, 02:43:58
0

Выбранная вами частота 200 Гц не является целым числом выборок на частоте 44,1 кГц. Если есть 44100 выборок /с /200 циклов /с, вы получите 220,5 выборок /цикл. Таким образом, в любое время nbWavesNeeded не является даже (чтобы исключить половину выборки) вашим adjustedDuration при переводе в frames имеет небольшую ошибку округления, которая приводит к появлению pop .

(После редактирования на 440 Гц проблема усугубляется, потому что 44100/440 имеет наибольший общий коэффициент)

  

Насколько я понял этот принцип, частота волн - это количество волн вверх и вниз в секунду. длительность ... длительность, а sampleRate - это количество срезов за одну секунду. Так что, если я нарежу волну на 1, 10, 50 или 1000 частей, это всегда одна и та же волна, только менее точная.

Это в основном правильно. Таким образом, в hertz = 440 есть «440 восходящих и нисходящих волн в секунду» и с sampleRate = 44100 ваш второй разделен на 44100 срезов. Сколько срезов занимает одна «волна вверх и вниз»? 1/440 секунды или 1/440 из ваших 44100 срезов, или 44100 / 440, что означает 100.2272727272... Так что, если frames == 100.22727272.., тогда точный конец «восходящей волны» будет соответствовать до точного конца вашего rawSound. Но frames является целым числом, поэтому вы остановитесь на frames = 100 так что вы сократили волну. Когда звуковой проигрыватель возвращается к 0, он действительно хочет вернуться к 0.2272727..., но, конечно, не может. Вы слышите это как поп.

ответил Ben Jackson 30 +04002011-10-30T06:49:36+04:00312011bEurope/MoscowSun, 30 Oct 2011 06:49:36 +0400 2011, 06:49:36
0

Способ генерации чистого непрерывного тона в iOS состоит не в том, чтобы использовать AVAudioPlayer и зависеть от него для правильной конкатенации аудиофрагментов, а в том, чтобы использовать API аудио-очереди или аудиоустройство RemoteIO и контролировать непрерывность передачи звука в буфере обратного вызова самостоятельно.

ответил hotpaw2 30 +04002011-10-30T20:05:23+04:00312011bEurope/MoscowSun, 30 Oct 2011 20:05:23 +0400 2011, 20:05:23
0

После просмотра ваших правок и образцов данных, я убедительно убежден, что вы избегаете ошибок, которые я описал в моем другом ответе, с конкретными значениями, которые вы выбрали.

Позвольте мне предложить альтернативу: AVAudioPlayer берет чередующиеся стерео сэмплы (потому что numberOfChannels равно 2), и когда вы представляете четное количество сэмплов, вы слышите два тона (один очень немного не в фазе с другим) с удвоенной предполагаемой частотой. Когда вы представляете нечетное число (как в вашем последнем примере), отсутствует один образец для одного канала, что приводит к появлению всплывающих окон.

Это неверное предположение, потому что я не разработчик для iOS и не могу понять, почему numberOfChannels только для чтения чтения-записи.

ответил Ben Jackson 31 +04002011-10-31T05:04:58+04:00312011bEurope/MoscowMon, 31 Oct 2011 05:04:58 +0400 2011, 05:04:58

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132