Beep with custom frequency and duration

杀马特。学长 韩版系。学妹 提交于 2019-12-10 20:51:31

问题


I want to play Beep sound in my Mac Os X and specify duration and frequency. On Windows it can be done by using Beep function (Console.Beep in .Net). Is there anything equivalent in Mac? I am aware of NSBeep but it does not take any parameters.


回答1:


On the Mac, the system alert sound is a sampled (prerecorded) sound that the user chooses. It often sounds nothing like a beep—it may be a honk, thunk, blare, or other sound that can't be as a simple constant waveform of fixed shape, frequency, and amplitude. It can even be a recording of the user's voice, or a clip from a TV show or movie or game or song.

It also does not need to be only a sound. One of the accessibility options is to flash the screen when an alert sound plays; this happens automatically when you play the alert sound (or a custom alert sound), but not when you play a sound through regular sound-playing APIs such as NSSound.

As such, there's no simple way to play a custom beep of a specified and constant shape, frequency, and amplitude. Any such beep would differ from the user's selected alert sound and may not be perceptible to the user at all.

To play the alert sound on the Mac, use NSBeep or the slightly more complicated AudioServicesPlayAlertSound. The latter allows you to use custom sounds, but even these must be prerecorded, or at least generated by your app in advance using more Core Audio code than is worth writing.

I recommend using NSBeep. It's one line of code to respect the user's choices.




回答2:


PortAudio has cross platform C code for doing this here: https://subversion.assembla.com/svn/portaudio/portaudio/trunk/examples/paex_sine.c

That particular sample generates tones on the left and right speaker, but doesn't show how the frequencies are calculated. For that, you can use the formula in this code: Is there an library in Java for emitting a certain frequency constantly?




回答3:


I needed a similar functionality for an app. I ended up writing a small, reusable class to handle this for me.

Source on GitHub

A reusable class for generating simple sine waveform audio tones with specified frequency and amplitude. Can play continuously or for a specified duration.

The interface is fairly straightforward and is shown below:

@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



回答4:


Here's a way of doing this with the newer AVAudioEngine/AVAudioNode APIs, and 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


来源:https://stackoverflow.com/questions/12547499/beep-with-custom-frequency-and-duration

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!