यहां एक नंगे हड्डियों का आवेदन है जो ऑन-डिमांड पर जनरेटेड आवृत्ति खेलेंगे। आपने यह निर्दिष्ट नहीं किया है कि आईओएस या ओएसएक्स करना है या नहीं, इसलिए मैं ओएसएक्स के लिए गया हूं क्योंकि यह थोड़ा आसान है (ऑडियो सत्र श्रेणियों के साथ कोई गड़बड़ नहीं है)। यदि आपको आईओएस की आवश्यकता है, तो आप ऑडियो सत्र श्रेणी मूल बातें देखकर और रिमोटियो ऑडियो इकाई के लिए डिफ़ॉल्ट आउटपुट ऑडियो इकाई को स्वैप करके लापता बिट्स को ढूंढ पाएंगे।
ध्यान दें कि इसका उद्देश्य कुछ कोर ऑडियो/ऑडियो यूनिट मूलभूत बातें प्रदर्शित करने के लिए पूरी तरह से है। यदि आप इस से अधिक जटिल होना शुरू करना चाहते हैं तो आप शायद AUGraph
एपीआई देखना चाहेंगे (एक साफ उदाहरण प्रदान करने के हित में भी, मैं कोई त्रुटि जांच नहीं कर रहा हूं। हमेशा से निपटने में त्रुटि की जांच करें कोर ऑडियो)।
आपको इस कोड का उपयोग करने के लिए अपनी परियोजना में AudioToolbox
और AudioUnit
ढांचे को जोड़ने की आवश्यकता होगी।
#import <AudioToolbox/AudioToolbox.h>
@interface SWAppDelegate : NSObject <NSApplicationDelegate>
{
AudioUnit outputUnit;
double renderPhase;
}
@end
@implementation SWAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// First, we need to establish which Audio Unit we want.
// We start with its description, which is:
AudioComponentDescription outputUnitDescription = {
.componentType = kAudioUnitType_Output,
.componentSubType = kAudioUnitSubType_DefaultOutput,
.componentManufacturer = kAudioUnitManufacturer_Apple
};
// Next, we get the first (and only) component corresponding to that description
AudioComponent outputComponent = AudioComponentFindNext(NULL, &outputUnitDescription);
// Now we can create an instance of that component, which will create an
// instance of the Audio Unit we're looking for (the default output)
AudioComponentInstanceNew(outputComponent, &outputUnit);
AudioUnitInitialize(outputUnit);
// Next we'll tell the output unit what format our generated audio will
// be in. Generally speaking, you'll want to stick to sane formats, since
// the output unit won't accept every single possible stream format.
// Here, we're specifying floating point samples with a sample rate of
// 44100 Hz in mono (i.e. 1 channel)
AudioStreamBasicDescription ASBD = {
.mSampleRate = 44100,
.mFormatID = kAudioFormatLinearPCM,
.mFormatFlags = kAudioFormatFlagsNativeFloatPacked,
.mChannelsPerFrame = 1,
.mFramesPerPacket = 1,
.mBitsPerChannel = sizeof(Float32) * 8,
.mBytesPerPacket = sizeof(Float32),
.mBytesPerFrame = sizeof(Float32)
};
AudioUnitSetProperty(outputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&ASBD,
sizeof(ASBD));
// Next step is to tell our output unit which function we'd like it
// to call to get audio samples. We'll also pass in a context pointer,
// which can be a pointer to anything you need to maintain state between
// render callbacks. We only need to point to a double which represents
// the current phase of the sine wave we're creating.
AURenderCallbackStruct callbackInfo = {
.inputProc = SineWaveRenderCallback,
.inputProcRefCon = &renderPhase
};
AudioUnitSetProperty(outputUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Global,
0,
&callbackInfo,
sizeof(callbackInfo));
// Here we're telling the output unit to start requesting audio samples
// from our render callback. This is the line of code that starts actually
// sending audio to your speakers.
AudioOutputUnitStart(outputUnit);
}
// This is our render callback. It will be called very frequently for short
// buffers of audio (512 samples per call on my machine).
OSStatus SineWaveRenderCallback(void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData)
{
// inRefCon is the context pointer we passed in earlier when setting the render callback
double currentPhase = *((double *)inRefCon);
// ioData is where we're supposed to put the audio samples we've created
Float32 * outputBuffer = (Float32 *)ioData->mBuffers[0].mData;
const double frequency = 440.;
const double phaseStep = (frequency/44100.) * (M_PI * 2.);
for(int i = 0; i < inNumberFrames; i++) {
outputBuffer[i] = sin(currentPhase);
currentPhase += phaseStep;
}
// If we were doing stereo (or more), this would copy our sine wave samples
// to all of the remaining channels
for(int i = 1; i < ioData->mNumberBuffers; i++) {
memcpy(ioData->mBuffers[i].mData, outputBuffer, ioData->mBuffers[i].mDataByteSize);
}
// writing the current phase back to inRefCon so we can use it on the next call
*((double *)inRefCon) = currentPhase;
return noErr;
}
- (void)applicationWillTerminate:(NSNotification *)notification
{
AudioOutputUnitStop(outputUnit);
AudioUnitUninitialize(outputUnit);
AudioComponentInstanceDispose(outputUnit);
}
@end
आप होगा पर AudioOutputUnitStart()
और AudioOutputUnitStop()
फोन शुरू/ऑडियो उत्पादन बंद कर सकते हैं। यदि आप आवृत्ति को गतिशील रूप से बदलना चाहते हैं, तो आप एक पॉइंटर में struct
पर पास कर सकते हैं जिसमें रेंडरफेस डबल और दूसरा एक आवृत्ति है जो आप चाहते हैं।
कॉलबैक प्रस्तुत करने में सावधान रहें। इसे रीयलटाइम थ्रेड से कहा जाता है (आपके मुख्य रन लूप के समान धागे से नहीं)। प्रस्तुत कॉलबैक काफी कुछ सख्त समय की आवश्यकताओं, जिसका अर्थ है वहाँ इस तरह के रूप में बहुत सी बातें अपने कॉलबैक में क्या नहीं करना चाहिए, यह है कि के अधीन हैं:
- एक फ़ाइल से स्मृति आवंटित
- प्रतीक्षा एक म्युटेक्स पर
- पढ़ें डिस्क पर
- ऑब्जेक्टिव-सी संदेश (हाँ, गंभीरता से।)
ध्यान दें कि यह यह करने के लिए एक ही रास्ता नहीं है। मैंने इसे इस तरह से प्रदर्शित किया है क्योंकि आपने इस कोर-ऑडियो को टैग किया है। यदि आपको आवृत्ति बदलने की आवश्यकता नहीं है तो आप अपनी साइन लहर वाली पूर्व-निर्मित ध्वनि फ़ाइल के साथ AVAudioPlayer
का उपयोग कर सकते हैं।
Novocaine भी है, जो आपके द्वारा इस वर्बोजिटी को बहुत अधिक छुपाता है। आप ऑडियो क्यूई एपीआई में भी देख सकते हैं, जो मैंने लिखा कोर ऑडियो नमूना के समान ही काम करता है लेकिन हार्डवेयर से आपको थोड़ा और कम करता है (यानी यह आपके बारे में कम सख्त है कि आप अपने रेंडर कॉलबैक में कैसे व्यवहार करते हैं)।
यह हो सकता है कि AVAudioPlayer मुझे प्रारंभ करने की आवश्यकता है ... – Rogare
AVAudioPlayer जाने का मार्ग होगा यदि आप सिर्फ साइन लहर की पूर्व-निर्मित ध्वनि फ़ाइल खेलना चाहते हैं (आप वॉल्यूम को नियंत्रित करने में सक्षम होंगे लेकिन आवृत्ति जैसे कुछ और नहीं)। – admsyn