Звуковой сигнал с пользовательской частотой и продолжительностью

Я хочу воспроизвести звуковой сигнал в своем Mac Os X и указать продолжительность и частоту. В Windows это можно сделать с помощью Функция звукового сигнала (Console.Beep в .Net) . Есть ли что-то подобное в Mac? Я знаю о NSBeep, но он не принимает никаких параметров.


person Giorgi    schedule 22.09.2012    source источник
comment
Разве вы не можете просто создать волну с помощью CoreAudio и воспроизвести ее?   -  person    schedule 23.09.2012


Ответы (4)


На Mac звук системного оповещения представляет собой сэмпл (предварительно записанный) звук, который выбирает пользователь. Часто это совсем не похоже на звуковой сигнал — это может быть гудок, удар, рев или другой звук, который не может быть простой постоянной формой волны фиксированной формы, частоты и амплитуды. Это может быть даже запись голоса пользователя, или отрывок из телешоу, или фильма, или игры, или песни.

Это также не обязательно должен быть только звук. Одним из вариантов специальных возможностей является мигание экрана при воспроизведении звукового сигнала; это происходит автоматически при воспроизведении звука предупреждения (или пользовательского звука предупреждения), но не при воспроизведении звука через обычные API-интерфейсы воспроизведения звука, такие как NSSound.

Таким образом, нет простого способа воспроизвести собственный звуковой сигнал заданной и постоянной формы, частоты и амплитуды. Любой такой звуковой сигнал будет отличаться от выбранного пользователем звука оповещения и может вообще не восприниматься пользователем.

Чтобы воспроизвести звуковой сигнал на Mac, используйте NSBeep или немного более сложный вариант AudioServicesPlayAlertSound. Последний позволяет вам использовать пользовательские звуки, но даже они должны быть предварительно записаны или, по крайней мере, сгенерированы вашим приложением заранее с использованием большего количества кода Core Audio, чем стоит писать.

Я рекомендую использовать NSBeep. Это одна строка кода для уважения выбора пользователя.

person Peter Hosey    schedule 22.09.2012
comment
Спасибо, это то, что я в итоге сделал. - person Giorgi; 22.10.2012

В PortAudio есть кроссплатформенный код C для этого: https://subversion.assembla.com/svn/portaudio/portaudio/trunk/examples/paex_sine.c

Этот конкретный образец генерирует тоны для левого и правого динамика, но не показывает, как рассчитываются частоты. Для этого вы можете использовать формулу в этом коде: -constantly">Есть ли в Java библиотека для постоянного излучения определенной частоты?

person Bjorn Roche    schedule 23.09.2012

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

Источник на GitHub

Многоразовый класс для генерации простых звуковых тонов синусоидальной формы с заданной частотой и амплитудой. Может воспроизводиться непрерывно или в течение заданного времени.

Интерфейс довольно прост и показан ниже:

@interface TGSineWaveToneGenerator : NSObject
{
    AudioComponentInstance toneUnit;

@public
    double frequency;
    double amplitude;
    double sampleRate;
    double theta;
}

- (id)initWithFrequency:(double)hertz amplitude:(double)volume;
- (void)playForDuration:(float)time;
- (void)play;
- (void)stop;

@end
person picciano    schedule 16.08.2013

Вот способ сделать это с помощью более новых API-интерфейсов AVAudioEngine/AVAudioNode и Swift:

import AVFoundation
import Accelerate

// Specify the audio format we're going to use
let sampleRateHz = 44100
let numChannels = 1
let pcmFormat = AVAudioFormat(standardFormatWithSampleRate: Double(sampleRateHz), channels: UInt32(numChannels))

let noteFrequencyHz = 440
let noteDuration: NSTimeInterval = 1

// Create a buffer for the audio data
let numSamples = UInt32(noteDuration * Double(sampleRateHz))
let buffer = AVAudioPCMBuffer(PCMFormat: pcmFormat, frameCapacity: numSamples)
buffer.frameLength = numSamples  // the buffer will be completely full

// The "standard format" is deinterleaved float, so we can assume the stride is 1.
assert(buffer.stride == 1)
for channelBuffer in UnsafeBufferPointer(start: buffer.floatChannelData, count: numChannels) {
    // Generate a sine wave with the specified frequency and duration
    var length = Int32(numSamples)
    var dc: Float = 0
    var multiplier: Float = 2*Float(M_PI)*Float(noteFrequencyHz)/Float(sampleRateHz)
    vDSP_vramp(&dc, &multiplier, channelBuffer, buffer.stride, UInt(numSamples))
    vvsinf(channelBuffer, channelBuffer, &length)
}

// Hook up a player and play the buffer, then exit
let engine = AVAudioEngine()
let player = AVAudioPlayerNode()
engine.attachNode(player)
engine.connect(player, to: engine.mainMixerNode, format: pcmFormat)
try! engine.start()
player.scheduleBuffer(buffer, completionHandler: { exit(1) })
player.play()

NSRunLoop.mainRunLoop().run()  // Keep running in a playground
person jtbandes    schedule 14.05.2016