РЕДАКТИРОВАТЬ после ответа Бена
Я пытаюсь сделать что-то, что должно быть очень легко для кого-то, кто используется с обработкой сигналов, но это доставляет мне головную боль. Я просто пытаюсь сгенерировать звуковой сигнал, который будет воспроизводиться произвольное количество секунд, может быть меньше или больше секунды (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
EDIT
Я записал сгенерированный звуковой образец (440 Гц, 444100 сэмплов, 0,1 секунды) в файл и открыл его с помощью звукового редактора. Вырезайте и вставляйте звук много раз, чтобы сделать его более длинным: он воспроизводится без щелчка. Один и тот же образец звука, воспроизводимый через AVAudioPlayer, генерирует щелчки в конце каждого образца. Так что, похоже, проблема в AVAudioPlayer, по причине, которую я не понимаю, потому что только некоторые конкретные значения генерируют эти клики.
EDIT
Я использовал сгенерированный файл wav и заставил его проигрываться с помощью AVAudioPlayer с циклом: clicks
Я использовал тот же файл и заставил его проигрывать цикл с OpenAL, используя пользовательскую библиотеку: больше никаких кликов. Проблема в том, что OpenAL действительно кошмар для понимания и приведет к полной перезаписи моей звуковой части, просто для этого плохого звука.
Проблема, по-видимому, заключается в использовании AVAudioPlayer. Если у вас было решение заставить его работать, это сэкономит мне время.