View in English

  • Apple Developer
    • Get Started

    Explore Get Started

    • Overview
    • Learn
    • Apple Developer Program

    Stay Updated

    • Latest News
    • Hello Developer
    • Platforms

    Explore Platforms

    • Apple Platforms
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    Featured

    • Design
    • Distribution
    • Games
    • Accessories
    • Web
    • Home
    • CarPlay
    • Technologies

    Explore Technologies

    • Overview
    • Xcode
    • Swift
    • SwiftUI

    Featured

    • Accessibility
    • App Intents
    • Apple Intelligence
    • Games
    • Machine Learning & AI
    • Security
    • Xcode Cloud
    • Community

    Explore Community

    • Overview
    • Meet with Apple events
    • Community-driven events
    • Developer Forums
    • Open Source

    Featured

    • WWDC
    • Swift Student Challenge
    • Developer Stories
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Centers
    • Documentation

    Explore Documentation

    • Documentation Library
    • Technology Overviews
    • Sample Code
    • Human Interface Guidelines
    • Videos

    Release Notes

    • Featured Updates
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • Downloads

    Explore Downloads

    • All Downloads
    • Operating Systems
    • Applications
    • Design Resources

    Featured

    • Xcode
    • TestFlight
    • Fonts
    • SF Symbols
    • Icon Composer
    • Support

    Explore Support

    • Overview
    • Help Guides
    • Developer Forums
    • Feedback Assistant
    • Contact Us

    Featured

    • Account Help
    • App Review Guidelines
    • App Store Connect Help
    • Upcoming Requirements
    • Agreements and Guidelines
    • System Status
  • Quick Links

    • Events
    • News
    • Forums
    • Sample Code
    • Videos
 

Vídeos

Abrir menu Fechar menu
  • Coleções
  • Todos os vídeos
  • Sobre

Mais vídeos

  • Sobre
  • Código
  • Create audio drivers with DriverKit

    Discover how to use the AudioDriverKit API to consolidate your Audio Server plug-in and DriverKit extension into a single package. Learn how you can simplify audio driver installation with an app instead of an installer package and distribute your driver through the Mac App Store. And we'll take you through how the Core Audio HAL interacts with AudioDriverKit and discover best practices for audio device drivers.

    Recursos

      • Vídeo HD
      • Vídeo SD

    Vídeos relacionados

    WWDC22

    • Bring your driver to iPad with DriverKit

    WWDC20

    • Modernize PCI and SCSI drivers with DriverKit

    WWDC19

    • System Extensions and DriverKit
  • Buscar neste vídeo...
    • 5:58 - Subclass of IOUserAudioDriver

      // SimpleAudioDriver example, subclass of IOUserAudioDriver
      
      class SimpleAudioDriver: public IOUserAudioDriver
      {
      public:
      	virtual bool init() override;
      	virtual void free() override;
      	
      	virtual kern_return_t Start(IOService* provider) override;	
      	virtual kern_return_t Stop(IOService* provider) override;
      	virtual kern_return_t NewUserClient(uint32_t in_type,
      										 IOUserClient** out_user_client) override;
      	
      	virtual kern_return_t StartDevice(IOUserAudioObjectID in_object_id,
      									   IOUserAudioStartStopFlags in_flags) override;
      	
      	virtual kern_return_t StopDevice(IOUserAudioObjectID in_object_id,
      									  IOUserAudioStartStopFlags in_flags) override;
    • 6:27 - Override of IOService::NewUserClient

      // SimpleAudioDriver example override of IOService::NewUserClient
      kern_return_t SimpleAudioDriver::NewUserClient_Impl(uint32_t in_type,
      													 IOUserClient** out_user_client)
      {
      	kern_return_t error = kIOReturnSuccess;
      	//	Have the super class create the IOUserAudioDriverUserClient object if the type is
      	//	kIOUserAudioDriverUserClientType
      	if (in_type == kIOUserAudioDriverUserClientType)
      	{
      		error = super::NewUserClient(in_type, out_user_client, SUPERDISPATCH);
      	}
      	else
      	{
      		IOService* user_client_service = nullptr;
      		error = Create(this, "SimpleAudioDriverUserClientProperties", &user_client_service);
      		FailIfError(error, , Failure, "failed to create the SimpleAudioDriver user-client");
      		*out_user_client = OSDynamicCast(IOUserClient, user_client_service);
      	}
      	return error;
      }
    • 7:04 - SimpleAudioDevice::init

      // SimpleAudioDevice::init, set device sample rates and create IOUserAudioStream object
      ...
          SetAvailableSampleRates(sample_rates, 2); 
          SetSampleRate(kSampleRate_1);
      
          //	Create the IOBufferMemoryDescriptor ring buffer for the input stream
          OSSharedPtr<IOBufferMemoryDescriptor> io_ring_buffer;
          const auto buffer_size_bytes = static_cast<uint32_t>(in_zero_timestamp_period *  
              sizeof(uint16_t) * input_channels_per_frame);
          IOBufferMemoryDescriptor::Create(kIOMemoryDirectionInOut, buffer_size_bytes, 0, 
             io_ring_buffer.attach());
      	
          //	Create input stream object and pass in the IO ring buffer memory descriptor
          ivars->m_input_stream = IOUserAudioStream::Create(in_driver, 
                                                            IOUserAudioStreamDirection::Input, 
                                                            io_ring_buffer.get());
      ...
    • 8:19 - SimpleAudioDevice::init continued

      // SimpleAudioDevice::init continued
          IOUserAudioStreamBasicDescription input_stream_formats[2] = {
                  kSampleRate_1, IOUserAudioFormatID::LinearPCM,
                  static_cast<IOUserAudioFormatFlags>(
                          IOUserAudioFormatFlags::FormatFlagIsSignedInteger | 
                          IOUserAudioFormatFlags::FormatFlagsNativeEndian),
                  static_cast<uint32_t>(sizeof(int16_t)*input_channels_per_frame),
                  1,
                  static_cast<uint32_t>(sizeof(int16_t)*input_channels_per_frame),
                  static_cast<uint32_t>(input_channels_per_frame),
                  16
      		    },
              ...
          }
      
          ivars->m_input_stream->SetAvailableStreamFormats(input_stream_formats, 2);
          ivars->m_input_stream_format = input_stream_formats[0];
          ivars->m_input_stream->SetCurrentStreamFormat(&ivars->m_input_stream_format);
      	
          error = AddStream(ivars->m_input_stream.get());
    • 8:50 - Create a input volume level control object

      //	Create volume control object for the input stream.
          ivars->m_input_volume_control = IOUserAudioLevelControl::Create(in_driver,
              true, -6.0, {-96.0, 0.0},
              IOUserAudioObjectPropertyElementMain,
              IOUserAudioObjectPropertyScope::Input,
              IOUserAudioClassID::VolumeControl);
      
          //	Add volume control to device
          error = AddControl(ivars->m_input_volume_control.get());
    • 9:22 - Create custom property

      // SimpleAudioDevice::init, Create custom property
      
      IOUserAudioObjectPropertyAddress prop_addr = {
          kSimpleAudioDriverCustomPropertySelector,
          IOUserAudioObjectPropertyScope::Global,
          IOUserAudioObjectPropertyElementMain
      };
      
      custom_property = IOUserAudioCustomProperty::Create(in_driver, prop_addr, true,
          IOUserAudioCustomPropertyDataType::String,
          IOUserAudioCustomPropertyDataType::String);
      
      qualifier = OSSharedPtr(
          OSString::withCString(kSimpleAudioDriverCustomPropertyQualifier0), OSNoRetain);
      data = OSSharedPtr(
          OSString::withCString(kSimpleAudioDriverCustomPropertyDataValue0), OSNoRetain);
      custom_property->SetQualifierAndDataValue(qualifier.get(), data.get());
      
      AddCustomProperty(custom_property.get());
    • 10:47 - Subclass of IOUserAudioDevice

      // SimpleAudioDevice example subclass of IOUserAudioDevice
      
      class SimpleAudioDevice: public IOUserAudioDevice
      {
      ...
          virtual kern_return_t StartIO(IOUserAudioStartStopFlags in_flags) final LOCALONLY;
          virtual kern_return_t StopIO(IOUserAudioStartStopFlags in_flags) final LOCALONLY;
      
      private:
          kern_return_t StartTimers() LOCALONLY;
          void StopTimers() LOCALONLY;
          void UpdateTimers() LOCALONLY;
          virtual void ZtsTimerOccurred(OSAction* action,
      								   uint64_t time) TYPE(IOTimerDispatchSource::TimerOccurred);
          virtual void ToneTimerOccurred(OSAction* action,
      									uint64_t time) TYPE(IOTimerDispatchSource::TimerOccurred);
          void GenerateToneForInput(size_t in_frame_size) LOCALONLY;
      }
    • 11:18 - StartIO

      // StartIO 
      kern_return_t SimpleAudioDevice::StartIO(IOUserAudioStartStopFlags in_flags)
      {
          __block kern_return_t error = kIOReturnSuccess;
          __block OSSharedPtr<IOMemoryDescriptor> input_iomd;
          ivars->m_work_queue->DispatchSync(^(){
      		//	Tell IOUserAudioObject base class to start IO for the device
              error = super::StartIO(in_flags);
              if (error == kIOReturnSuccess)
              {
                  // Get stream IOMemoryDescriptor, create mapping and store to ivars	
                  input_iomd = ivars->m_input_stream->GetIOMemoryDescriptor();
                  input_iomd->CreateMapping(0, 0, 0, 0, 0, ivars->m_input_memory_map.attach());
      
                  // Start timers to send timestamps and generate sine tone on the stream buffer	
                  StartTimers();
              }
          });
          return error;
      }
    • 11:57 - StartTimers

      kern_return_t SimpleAudioDevice::StartTimers()
      {
      ...
      	//	clear the device's timestamps
      	UpdateCurrentZeroTimestamp(0, 0);
      	auto current_time = mach_absolute_time();
      	auto wake_time = current_time + ivars->m_zts_host_ticks_per_buffer;
      	
      	//	start the timer, the first time stamp will be taken when it goes off
      	ivars->m_zts_timer_event_source->WakeAtTime(kIOTimerClockMachAbsoluteTime,
      												 wake_time,
      												 0);
      	ivars->m_zts_timer_event_source->SetEnable(true);
      ...
      }
    • 12:27 - ZtsTimerOccurred

      void SimpleAudioDevice::ZtsTimerOccurred_Impl(OSAction* action, uint64_t time)
      {
      ...
      	GetCurrentZeroTimestamp(&current_sample_time, &current_host_time);
      	auto host_ticks_per_buffer = ivars->m_zts_host_ticks_per_buffer;
      	if (current_host_time != 0) {
      		current_sample_time += GetZeroTimestampPeriod();
      		current_host_time += host_ticks_per_buffer;
      	}
      	else {
      		current_sample_time = 0;
      		current_host_time = time;
      	}
      	// Update the device with the current timestamp
      	UpdateCurrentZeroTimestamp(current_sample_time, current_host_time);
      
      	//	set the timer to go off in one buffer
      	ivars->m_zts_timer_event_source->WakeAtTime(kIOTimerClockMachAbsoluteTime,
      												current_host_time + host_ticks_per_buffer, 0);
      }
    • 13:03 - GenerateToneForInput

      void SimpleAudioDevice::GenerateToneForInput(size_t in_frame_size) 
      {
      	// Fill out the input buffer with a sine tone
      	if (ivars->m_input_memory_map)
      	{
      		//	Get the pointer to the IO buffer and use stream format information
      		//	to get buffer length
      		const auto& format = ivars->m_input_stream_format;
      		auto buffer_length = ivars->m_input_memory_map->GetLength() / 
                  (format.mBytesPerFrame / format.mChannelsPerFrame);
      		auto num_samples = in_frame_size;
      		auto buffer = reinterpret_cast<int16_t*>(ivars->m_input_memory_map->GetAddress() +  
                  ivars->m_input_memory_map->GetOffset());
      ...	
      }
    • 13:30 - GenerateToneForInput continued

      void SimpleAudioDevice::GenerateToneForInput(size_t in_frame_size) 
      {
      ...
      	auto input_volume_level = ivars->m_input_volume_control->GetScalarValue();
      
      	for (size_t i = 0; i < num_samples; i++)
      	{
      		float float_value = input_volume_level * 
          sin(2.0 * M_PI * frequency * 
             static_cast<double>(ivars->m_tone_sample_index) / format.mSampleRate);
      
      		int16_t integer_value = FloatToInt16(float_value);
      		for (auto ch_index = 0; ch_index < format.mChannelsPerFrame; ch_index++)
      		{
      			auto buffer_index =
                      (format.mChannelsPerFrame * ivars->m_tone_sample_index + ch_index) %         
                      buffer_length;
      			buffer[buffer_index] = integer_value;
      		}
      		ivars->m_tone_sample_index += 1;
      	}
      }
    • 14:02 - IOUserAudioClockDevice.h and IOUserAudioDevice.h

      // IOUserAudioClockDevice.h and IOUserAudioDevice.h
      
      kern_return_t RequestDeviceConfigurationChange(uint64_t in_change_action,
      											    OSObject* in_change_info);
      
      virtual kern_return_t PerformDeviceConfigurationChange(uint64_t in_change_action,
      											            OSObject* in_change_info);
      
      virtual kern_return_t AbortDeviceConfigurationChange(uint64_t change_action,
      													  OSObject* in_change_info);
    • 15:32 - HandleTestConfigChange

      kern_return_t SimpleAudioDriver::HandleTestConfigChange()
      {
      	auto change_info = OSSharedPtr(OSString::withCString("Toggle Sample Rate"), OSNoRetain);
      	return ivars->m_simple_audio_device->RequestDeviceConfigurationChange(
              k_custom_config_change_action, change_info.get());
      }
      
      class SimpleAudioDevice: public IOUserAudioDevice
      {
      ...
      	virtual kern_return_t PerformDeviceConfigurationChange(uint64_t change_action,
      												    OSObject* in_change_info) final LOCALONLY;
      }
    • 16:05 - PerformDeviceConfigurationChange

      // In SimpleAudioDevice::PerformDeviceConfigurationChange
      	kern_return_t ret = kIOReturnSuccess;
      	switch (change_action) {
      		case k_custom_config_change_action: {
      			if (in_change_info)	{
      				auto change_info_string = OSDynamicCast(OSString, in_change_info);
      				DebugMsg("%s", change_info_string->getCStringNoCopy());
      			}
      
      			double rate_to_set = static_cast<uint64_t>(GetSampleRate()) != 
                      static_cast<uint64_t>(kSampleRate_1) ? kSampleRate_1 : kSampleRate_2;
      			ret = SetSampleRate(rate_to_set);
      			if (ret == kIOReturnSuccess) {
      				// Update stream formats with the new rate
      				ret = ivars->m_input_stream->DeviceSampleRateChanged(rate_to_set);
      			}
      		}
      			break;
      			
      		default:
      			ret = super::PerformDeviceConfigurationChange(change_action, in_change_info);
      			break;
      	}
      	
      	// Update the cached format:
      	ivars->m_input_stream_format = ivars->m_input_stream->GetCurrentStreamFormat();
      	
      	return ret;
      }

Developer Footer

  • Vídeos
  • WWDC21
  • Create audio drivers with DriverKit
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • Apple Intelligence
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Downloads
    • Sample Code
    • Videos
    Open Menu Close Menu
    • Help Guides & Articles
    • Contact Us
    • Forums
    • Feedback & Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program
    • Mini Apps Partner Program
    • News Partner Program
    • Video Partner Program
    • Security Bounty Program
    • Security Research Device Program
    Open Menu Close Menu
    • Meet with Apple
    • Apple Developer Centers
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • WWDC
    Read the latest news.
    Get the Apple Developer app.
    Copyright © 2026 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines