我想在我的 Mac Os X 中播放哔声并指定持续时间和频率。在 Windows 上,可以使用Beep 功能(.Net 中的Console.Beep )来完成。Mac有什么等价的吗?我知道 NSBeep 但它不带任何参数。
4 回答
在 Mac 上,系统警报声音是用户选择的采样(预录)声音。它通常听起来不像哔哔声——它可能是喇叭声、砰砰声、喇叭声或其他不能作为固定形状、频率和幅度的简单恒定波形的声音。它甚至可以是用户声音的录音,或者是电视节目、电影、游戏或歌曲的剪辑。
它也不必只是一个声音。可访问性选项之一是在播放警报声时闪烁屏幕;这会在您播放警报声音(或自定义警报声音)时自动发生,但不会在您通过常规声音播放 API(如 NSSound)播放声音时发生。
因此,没有简单的方法可以播放具有指定和恒定形状、频率和幅度的自定义哔声。任何这样的蜂鸣声都会与用户选择的警报声音不同,并且用户可能根本察觉不到。
要在 Mac 上播放警报声,请使用NSBeep
或稍微复杂一点的AudioServicesPlayAlertSound
. 后者允许您使用自定义声音,但即使这些声音也必须预先录制,或者至少由您的应用程序预先使用更多的 Core Audio 代码生成,而不是值得编写。
我建议使用NSBeep
. 这是尊重用户选择的一行代码。
PortAudio 在这里有跨平台的 C 代码:https ://subversion.assembla.com/svn/portaudio/portaudio/trunk/examples/paex_sine.c
该特定样本在左右扬声器上产生音调,但没有显示频率是如何计算的。为此,您可以使用此代码中的公式:Java 中是否有一个库可以不断发出特定频率?
我需要一个类似的应用程序功能。我最终编写了一个小型的、可重用的类来为我处理这个问题。
一个可重用的类,用于生成具有指定频率和幅度的简单正弦波形音频。可以连续播放或指定持续时间。
界面相当简单,如下所示:
@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
这是使用较新的 AVAudioEngine/AVAudioNode API 和 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