From b96e0ad2d4a8f4f3371ce5840ae958425914c4f2 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Sun, 22 Aug 2021 18:45:40 -0700 Subject: [PATCH 01/37] Enable Opus CUSTOM_MODES --- Package.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Package.swift b/Package.swift index 2a853d4..265b1a6 100644 --- a/Package.swift +++ b/Package.swift @@ -88,6 +88,7 @@ let package = Package( .headerSearchPath("silk/float"), .define("OPUS_BUILD"), + .define("CUSTOM_MODES") .define("VAR_ARRAYS", to: "1"), .define("FLOATING_POINT"), // Enable Opus floating-point mode From 144063f51c471cba7f5d23d9ba133bfd2392277d Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Sun, 22 Aug 2021 18:47:25 -0700 Subject: [PATCH 02/37] Add comma --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 265b1a6..8c10e62 100644 --- a/Package.swift +++ b/Package.swift @@ -88,7 +88,7 @@ let package = Package( .headerSearchPath("silk/float"), .define("OPUS_BUILD"), - .define("CUSTOM_MODES") + .define("CUSTOM_MODES"), .define("VAR_ARRAYS", to: "1"), .define("FLOATING_POINT"), // Enable Opus floating-point mode From fb5c31c9f9fe12e4da9b877d05e4acfe48729208 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Mon, 23 Aug 2021 08:59:44 -0700 Subject: [PATCH 03/37] Add CELT headers / source --- Package.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Package.swift b/Package.swift index 8c10e62..9a0546f 100644 --- a/Package.swift +++ b/Package.swift @@ -27,8 +27,6 @@ let package = Package( exclude: [ "AUTHORS", "autogen.sh", - "celt_headers.mk", - "celt_sources.mk", "celt/arm", "celt/dump_modes", "celt/meson.build", From 04fa5158eb0c9013e16d5ca8c51dc9d07117c25f Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Mon, 23 Aug 2021 09:05:37 -0700 Subject: [PATCH 04/37] Include base header / source makefiles --- Package.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Package.swift b/Package.swift index 9a0546f..bb2b5a8 100644 --- a/Package.swift +++ b/Package.swift @@ -50,8 +50,6 @@ let package = Package( "meson.build", "meson", "NEWS", - "opus_headers.mk", - "opus_sources.mk", "opus-uninstalled.pc.in", "opus.m4", "opus.pc.in", From db32719b947ca3d255ca82bc3e5a4b7282a378e9 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Mon, 23 Aug 2021 09:45:26 -0700 Subject: [PATCH 05/37] Wrap variadic ctl functions for swift to import --- Sources/Copus-wrapper/variadic-wrapper.c | 11 +++++++++++ Sources/Copus-wrapper/variadic-wrapper.h | 11 +++++++++++ 2 files changed, 22 insertions(+) create mode 100644 Sources/Copus-wrapper/variadic-wrapper.c create mode 100644 Sources/Copus-wrapper/variadic-wrapper.h diff --git a/Sources/Copus-wrapper/variadic-wrapper.c b/Sources/Copus-wrapper/variadic-wrapper.c new file mode 100644 index 0000000..66f1974 --- /dev/null +++ b/Sources/Copus-wrapper/variadic-wrapper.c @@ -0,0 +1,11 @@ +#include "variadic-wrapper.h" + +int opus_custom_encoder_ctl_wrapper(CELTEncoder *OPUS_RESTRICT st, int request, opus_int32 val) +{ + opus_custom_encoder_ctl(st, request, val); +} + +int opus_custom_decoder_ctl_wrapper(CELTEncoder *OPUS_RESTRICT st, int request, opus_int32 val) +{ + opus_custom_decoder_ctl(st, request, val); +} diff --git a/Sources/Copus-wrapper/variadic-wrapper.h b/Sources/Copus-wrapper/variadic-wrapper.h new file mode 100644 index 0000000..e04008e --- /dev/null +++ b/Sources/Copus-wrapper/variadic-wrapper.h @@ -0,0 +1,11 @@ +#ifndef __OPUS_VARIADIC_WRAPPER_H__ +#define __OPUS_VARIADIC_WRAPPER_H__ + +#include +#include +#include + +int opus_custom_encoder_ctl_wrapper(CELTEncoder *OPUS_RESTRICT st, int request, opus_int32 val); +int opus_custom_decoder_ctl_wrapper(CELTEncoder *OPUS_RESTRICT st, int request, opus_int32 val); + +#endif From d1be9a62597e2c13c4cd9b82fe97d440bf813e06 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Mon, 23 Aug 2021 12:07:08 -0700 Subject: [PATCH 06/37] Wrap up some variadic functions --- .gitignore | 2 ++ Package.swift | 14 +++++++++++++- Sources/Copus-wrapper/variadic-wrapper.c | 4 ++-- Sources/Copus-wrapper/variadic-wrapper.h | 6 +++--- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index da64042..fcad177 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .build .DS_Store +DerivedData +.swiftpm diff --git a/Package.swift b/Package.swift index bb2b5a8..a920762 100644 --- a/Package.swift +++ b/Package.swift @@ -14,6 +14,10 @@ let package = Package( name: "Copus", targets: ["Copus"] ), + .library( + name: "Copus-wrapper", + targets: ["Copus-wrapper"] + ), .library( name: "Opus", targets: ["Opus", "Copus"] @@ -28,6 +32,8 @@ let package = Package( "AUTHORS", "autogen.sh", "celt/arm", + "celt_headers.mk", + "celt_sources.mk", "celt/dump_modes", "celt/meson.build", "celt/opus_custom_demo.c", @@ -50,6 +56,8 @@ let package = Package( "meson.build", "meson", "NEWS", + "opus_headers.mk", + "opus_sources.mk", "opus-uninstalled.pc.in", "opus.m4", "opus.pc.in", @@ -102,9 +110,13 @@ let package = Package( .define("HAVE_UNISTD_H", to: "1"), ] ), + .target( + name: "Copus-wrapper", + dependencies: ["Copus"] + ), .target( name: "Opus", - dependencies: ["Copus"] + dependencies: ["Copus", "Copus-wrapper"] ), .testTarget( name: "OpusTests", diff --git a/Sources/Copus-wrapper/variadic-wrapper.c b/Sources/Copus-wrapper/variadic-wrapper.c index 66f1974..15503e0 100644 --- a/Sources/Copus-wrapper/variadic-wrapper.c +++ b/Sources/Copus-wrapper/variadic-wrapper.c @@ -1,11 +1,11 @@ #include "variadic-wrapper.h" -int opus_custom_encoder_ctl_wrapper(CELTEncoder *OPUS_RESTRICT st, int request, opus_int32 val) +int opus_custom_encoder_ctl_wrapper(OpusCustomEncoder *OPUS_RESTRICT st, int request, opus_int32 val) { opus_custom_encoder_ctl(st, request, val); } -int opus_custom_decoder_ctl_wrapper(CELTEncoder *OPUS_RESTRICT st, int request, opus_int32 val) +int opus_custom_decoder_ctl_wrapper(OpusCustomDecoder *OPUS_RESTRICT st, int request, opus_int32 val) { opus_custom_decoder_ctl(st, request, val); } diff --git a/Sources/Copus-wrapper/variadic-wrapper.h b/Sources/Copus-wrapper/variadic-wrapper.h index e04008e..747a477 100644 --- a/Sources/Copus-wrapper/variadic-wrapper.h +++ b/Sources/Copus-wrapper/variadic-wrapper.h @@ -1,11 +1,11 @@ #ifndef __OPUS_VARIADIC_WRAPPER_H__ #define __OPUS_VARIADIC_WRAPPER_H__ -#include +//#include "" #include #include -int opus_custom_encoder_ctl_wrapper(CELTEncoder *OPUS_RESTRICT st, int request, opus_int32 val); -int opus_custom_decoder_ctl_wrapper(CELTEncoder *OPUS_RESTRICT st, int request, opus_int32 val); +int opus_custom_encoder_ctl_wrapper(OpusCustomEncoder *OPUS_RESTRICT st, int request, opus_int32 val); +int opus_custom_decoder_ctl_wrapper(OpusCustomDecoder *OPUS_RESTRICT st, int request, opus_int32 val); #endif From 80f7e0f580645b80dd5ef74b20dc4f7b28a066a0 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Mon, 23 Aug 2021 12:16:01 -0700 Subject: [PATCH 07/37] rename to copuswrapper --- Package.swift | 8 ++++---- .../{Copus-wrapper => Copuswrapper}/variadic-wrapper.c | 0 .../{Copus-wrapper => Copuswrapper}/variadic-wrapper.h | 0 3 files changed, 4 insertions(+), 4 deletions(-) rename Sources/{Copus-wrapper => Copuswrapper}/variadic-wrapper.c (100%) rename Sources/{Copus-wrapper => Copuswrapper}/variadic-wrapper.h (100%) diff --git a/Package.swift b/Package.swift index a920762..7d815f3 100644 --- a/Package.swift +++ b/Package.swift @@ -15,8 +15,8 @@ let package = Package( targets: ["Copus"] ), .library( - name: "Copus-wrapper", - targets: ["Copus-wrapper"] + name: "Copuswrapper", + targets: ["Copuswrapper"] ), .library( name: "Opus", @@ -111,12 +111,12 @@ let package = Package( ] ), .target( - name: "Copus-wrapper", + name: "Copuswrapper", dependencies: ["Copus"] ), .target( name: "Opus", - dependencies: ["Copus", "Copus-wrapper"] + dependencies: ["Copus", "Copuswrapper"] ), .testTarget( name: "OpusTests", diff --git a/Sources/Copus-wrapper/variadic-wrapper.c b/Sources/Copuswrapper/variadic-wrapper.c similarity index 100% rename from Sources/Copus-wrapper/variadic-wrapper.c rename to Sources/Copuswrapper/variadic-wrapper.c diff --git a/Sources/Copus-wrapper/variadic-wrapper.h b/Sources/Copuswrapper/variadic-wrapper.h similarity index 100% rename from Sources/Copus-wrapper/variadic-wrapper.h rename to Sources/Copuswrapper/variadic-wrapper.h From dc5f841d1c290aaa2a897be11816082c6af92505 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Mon, 23 Aug 2021 12:21:59 -0700 Subject: [PATCH 08/37] Move external header to export directory --- Package.swift | 6 +++++- Sources/Copuswrapper/{ => include}/variadic-wrapper.h | 0 2 files changed, 5 insertions(+), 1 deletion(-) rename Sources/Copuswrapper/{ => include}/variadic-wrapper.h (100%) diff --git a/Package.swift b/Package.swift index 7d815f3..ab98add 100644 --- a/Package.swift +++ b/Package.swift @@ -112,7 +112,11 @@ let package = Package( ), .target( name: "Copuswrapper", - dependencies: ["Copus"] + dependencies: ["Copus"], + publicHeadersPath: "include", + cSettings: [ + .headerSearchPath(".") + ] ), .target( name: "Opus", diff --git a/Sources/Copuswrapper/variadic-wrapper.h b/Sources/Copuswrapper/include/variadic-wrapper.h similarity index 100% rename from Sources/Copuswrapper/variadic-wrapper.h rename to Sources/Copuswrapper/include/variadic-wrapper.h From 4e452fd3e620a5623d57edde950487cb1bd4d76b Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Fri, 18 Mar 2022 14:09:11 -0700 Subject: [PATCH 09/37] Add custom mode extensions to support Jamulus --- Sources/Opus/Opus.Custom.swift | 49 +++++++++++++++++++++++++++++++++ Sources/Opus/Opus.Encoder.swift | 1 - 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 Sources/Opus/Opus.Custom.swift diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift new file mode 100644 index 0000000..af01884 --- /dev/null +++ b/Sources/Opus/Opus.Custom.swift @@ -0,0 +1,49 @@ +import AVFoundation +import Copus +import Foundation + +public extension Opus { + class Custom { + private let opusCustomMode: OpaquePointer + private let encoder: OpaquePointer + private let decoder: OpaquePointer + + public init(format: AVAudioFormat, + application: Application = .audio, + frameSize: UInt32 = 128) throws { + if !format.isValidOpusPCMFormat { + throw Opus.Error.badArgument + } + + var error: Opus.Error = .ok + + // Create custom parameters + guard let customMode = opus_custom_mode_create( + Int32(format.sampleRate), + Int32(frameSize), + &error.rawValue) else { throw error } + opusCustomMode = customMode + + // Create custom encoder + guard let opusEncoder = opus_custom_encoder_create( + customMode, + Int32(format.channelCount), + &error.rawValue) else { throw error } + encoder = opusEncoder + + // Create custom decoder + guard let opusDecoder = opus_custom_decoder_create( + customMode, + Int32(format.channelCount), + &error.rawValue) else { throw error } + decoder = opusDecoder + } + + deinit { + opus_custom_decoder_destroy(decoder) + opus_custom_encoder_destroy(encoder) + opus_custom_mode_destroy(opusCustomMode) + } + } +} + diff --git a/Sources/Opus/Opus.Encoder.swift b/Sources/Opus/Opus.Encoder.swift index 37dac29..69f5eef 100644 --- a/Sources/Opus/Opus.Encoder.swift +++ b/Sources/Opus/Opus.Encoder.swift @@ -7,7 +7,6 @@ public extension Opus { let application: Application let encoder: OpaquePointer - // TODO: throw an error if format is unsupported public init(format: AVAudioFormat, application: Application = .audio) throws { if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument From 6104386c2393bb10493f2c4a247c2658a9d066fe Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Fri, 18 Mar 2022 14:22:31 -0700 Subject: [PATCH 10/37] Add jamulus custom configuration --- Sources/Opus/Opus.Custom.Jamulus.swift | 50 ++++++++++++++++++++++++++ Sources/Opus/Opus.Custom.swift | 4 +-- 2 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 Sources/Opus/Opus.Custom.Jamulus.swift diff --git a/Sources/Opus/Opus.Custom.Jamulus.swift b/Sources/Opus/Opus.Custom.Jamulus.swift new file mode 100644 index 0000000..be21ce5 --- /dev/null +++ b/Sources/Opus/Opus.Custom.Jamulus.swift @@ -0,0 +1,50 @@ +// +// File.swift +// +// +// Created by Emlyn Bolton on 2022-03-18. +// + +import Copuswrapper +import Foundation + +public extension Opus.Custom { + + /// + /// Sets up jamulus-specific parts of the custom opus implementation + /// + func configureForJamulus(frameSize: UInt32 = 128) throws { + var error: Opus.Error = .ok + + // Disable variable bit rates + error.rawValue = opus_custom_encoder_ctl_wrapper( + encoder, + OPUS_SET_VBR_REQUEST, 0) + guard error == .ok else { throw error } + + // Request low latency + error.rawValue = opus_custom_encoder_ctl_wrapper( + encoder, + OPUS_SET_APPLICATION_REQUEST, OPUS_APPLICATION_RESTRICTED_LOWDELAY) + guard error == .ok else { throw error } + + switch frameSize { + case 64: + // Adjust PLC behaviour for better drop out handling + error.rawValue = opus_custom_encoder_ctl_wrapper( + encoder, + OPUS_SET_PACKET_LOSS_PERC_REQUEST, 35) + guard error == .ok else { throw error } + + case 128: + // Set complexity for 128 sample frame size + error.rawValue = opus_custom_encoder_ctl_wrapper( + encoder, + OPUS_SET_COMPLEXITY_REQUEST, 1) + guard error == .ok else { throw error } + + default: + break + } + } +} diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index af01884..d886ce0 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -5,8 +5,8 @@ import Foundation public extension Opus { class Custom { private let opusCustomMode: OpaquePointer - private let encoder: OpaquePointer - private let decoder: OpaquePointer + let encoder: OpaquePointer + let decoder: OpaquePointer public init(format: AVAudioFormat, application: Application = .audio, From 7273180624b150aa754eb43d817eba5ec90ea645 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Fri, 18 Mar 2022 15:57:55 -0700 Subject: [PATCH 11/37] Enable custom encoder / decoders to create higher level wrapper classes; add these to the custom implementation --- Sources/Opus/Opus.Custom.Jamulus.swift | 8 ++++---- Sources/Opus/Opus.Custom.swift | 15 +++++++++------ Sources/Opus/Opus.Decoder.swift | 19 ++++++++++++------- Sources/Opus/Opus.Encoder.swift | 16 +++++++++++----- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/Sources/Opus/Opus.Custom.Jamulus.swift b/Sources/Opus/Opus.Custom.Jamulus.swift index be21ce5..e5a9ea6 100644 --- a/Sources/Opus/Opus.Custom.Jamulus.swift +++ b/Sources/Opus/Opus.Custom.Jamulus.swift @@ -18,13 +18,13 @@ public extension Opus.Custom { // Disable variable bit rates error.rawValue = opus_custom_encoder_ctl_wrapper( - encoder, + encoder.encoder, OPUS_SET_VBR_REQUEST, 0) guard error == .ok else { throw error } // Request low latency error.rawValue = opus_custom_encoder_ctl_wrapper( - encoder, + encoder.encoder, OPUS_SET_APPLICATION_REQUEST, OPUS_APPLICATION_RESTRICTED_LOWDELAY) guard error == .ok else { throw error } @@ -32,14 +32,14 @@ public extension Opus.Custom { case 64: // Adjust PLC behaviour for better drop out handling error.rawValue = opus_custom_encoder_ctl_wrapper( - encoder, + encoder.encoder, OPUS_SET_PACKET_LOSS_PERC_REQUEST, 35) guard error == .ok else { throw error } case 128: // Set complexity for 128 sample frame size error.rawValue = opus_custom_encoder_ctl_wrapper( - encoder, + encoder.encoder, OPUS_SET_COMPLEXITY_REQUEST, 1) guard error == .ok else { throw error } diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index d886ce0..71d5191 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -5,8 +5,8 @@ import Foundation public extension Opus { class Custom { private let opusCustomMode: OpaquePointer - let encoder: OpaquePointer - let decoder: OpaquePointer + internal let encoder: Opus.Encoder + internal let decoder: Opus.Decoder public init(format: AVAudioFormat, application: Application = .audio, @@ -29,19 +29,22 @@ public extension Opus { customMode, Int32(format.channelCount), &error.rawValue) else { throw error } - encoder = opusEncoder + + encoder = try Opus.Encoder(format: format, + application: application, + customEncoder: opusEncoder) // Create custom decoder guard let opusDecoder = opus_custom_decoder_create( customMode, Int32(format.channelCount), &error.rawValue) else { throw error } - decoder = opusDecoder + decoder = try Opus.Decoder(format: format, + application: application, + customDecoder: opusDecoder) } deinit { - opus_custom_decoder_destroy(decoder) - opus_custom_encoder_destroy(encoder) opus_custom_mode_destroy(opusCustomMode) } } diff --git a/Sources/Opus/Opus.Decoder.swift b/Sources/Opus/Opus.Decoder.swift index 7d3ef23..2753c53 100644 --- a/Sources/Opus/Opus.Decoder.swift +++ b/Sources/Opus/Opus.Decoder.swift @@ -6,8 +6,9 @@ public extension Opus { let format: AVAudioFormat let decoder: OpaquePointer - // TODO: throw an error if format is unsupported - public init(format: AVAudioFormat, application _: Application = .audio) throws { + public init(format: AVAudioFormat, + application _: Application = .audio, + customDecoder: OpaquePointer? = nil) throws { if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument } @@ -16,11 +17,15 @@ public extension Opus { // Initialize Opus decoder var error: Opus.Error = .ok - decoder = opus_decoder_create(Int32(format.sampleRate), Int32(format.channelCount), &error.rawValue) - if error != .ok { - throw error - } - } + if let custom = customDecoder { + decoder = custom + } else { + decoder = opus_decoder_create(Int32(format.sampleRate), Int32(format.channelCount), &error.rawValue) + if error != .ok { + throw error + } + } + } deinit { opus_decoder_destroy(decoder) diff --git a/Sources/Opus/Opus.Encoder.swift b/Sources/Opus/Opus.Encoder.swift index 69f5eef..6cb4578 100644 --- a/Sources/Opus/Opus.Encoder.swift +++ b/Sources/Opus/Opus.Encoder.swift @@ -7,7 +7,9 @@ public extension Opus { let application: Application let encoder: OpaquePointer - public init(format: AVAudioFormat, application: Application = .audio) throws { + public init(format: AVAudioFormat, + application: Application = .audio, + customEncoder: OpaquePointer? = nil) throws { if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument } @@ -17,10 +19,14 @@ public extension Opus { // Initialize Opus encoder var error: Opus.Error = .ok - encoder = opus_encoder_create(Int32(format.sampleRate), Int32(format.channelCount), application.rawValue, &error.rawValue) - if error != .ok { - throw error - } + if let custom = customEncoder { + encoder = custom + } else { + encoder = opus_encoder_create(Int32(format.sampleRate), Int32(format.channelCount), application.rawValue, &error.rawValue) + if error != .ok { + throw error + } + } } deinit { From 40be05dd4bed0312e21deb0f1aec159356feea9c Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Fri, 18 Mar 2022 16:10:18 -0700 Subject: [PATCH 12/37] Enable access outside the module --- Sources/Opus/Opus.Custom.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index 71d5191..a516aa6 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -5,8 +5,8 @@ import Foundation public extension Opus { class Custom { private let opusCustomMode: OpaquePointer - internal let encoder: Opus.Encoder - internal let decoder: Opus.Decoder + let encoder: Opus.Encoder + let decoder: Opus.Decoder public init(format: AVAudioFormat, application: Application = .audio, From 593766dfb033a7558452dfb94566bdb68c85f554 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Sun, 20 Mar 2022 09:16:57 -0700 Subject: [PATCH 13/37] Add custom decode / encode functions and contain frameSize --- Sources/Opus/Opus.Custom.Jamulus.swift | 10 +- Sources/Opus/Opus.Custom.swift | 183 +++++++++++++++++++++++-- Sources/Opus/Opus.Decoder.swift | 17 +-- Sources/Opus/Opus.Encoder.swift | 13 +- 4 files changed, 190 insertions(+), 33 deletions(-) diff --git a/Sources/Opus/Opus.Custom.Jamulus.swift b/Sources/Opus/Opus.Custom.Jamulus.swift index e5a9ea6..2af18b7 100644 --- a/Sources/Opus/Opus.Custom.Jamulus.swift +++ b/Sources/Opus/Opus.Custom.Jamulus.swift @@ -13,18 +13,18 @@ public extension Opus.Custom { /// /// Sets up jamulus-specific parts of the custom opus implementation /// - func configureForJamulus(frameSize: UInt32 = 128) throws { + func configureForJamulus() throws { var error: Opus.Error = .ok // Disable variable bit rates error.rawValue = opus_custom_encoder_ctl_wrapper( - encoder.encoder, + encoder, OPUS_SET_VBR_REQUEST, 0) guard error == .ok else { throw error } // Request low latency error.rawValue = opus_custom_encoder_ctl_wrapper( - encoder.encoder, + encoder, OPUS_SET_APPLICATION_REQUEST, OPUS_APPLICATION_RESTRICTED_LOWDELAY) guard error == .ok else { throw error } @@ -32,14 +32,14 @@ public extension Opus.Custom { case 64: // Adjust PLC behaviour for better drop out handling error.rawValue = opus_custom_encoder_ctl_wrapper( - encoder.encoder, + encoder, OPUS_SET_PACKET_LOSS_PERC_REQUEST, 35) guard error == .ok else { throw error } case 128: // Set complexity for 128 sample frame size error.rawValue = opus_custom_encoder_ctl_wrapper( - encoder.encoder, + encoder, OPUS_SET_COMPLEXITY_REQUEST, 1) guard error == .ok else { throw error } diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index a516aa6..11c5102 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -5,8 +5,10 @@ import Foundation public extension Opus { class Custom { private let opusCustomMode: OpaquePointer - let encoder: Opus.Encoder - let decoder: Opus.Decoder + let encoder: OpaquePointer + let decoder: OpaquePointer + private let format: AVAudioFormat + let frameSize: Int32 public init(format: AVAudioFormat, application: Application = .audio, @@ -14,6 +16,8 @@ public extension Opus { if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument } + self.format = format + self.frameSize = Int32(frameSize) var error: Opus.Error = .ok @@ -30,23 +34,186 @@ public extension Opus { Int32(format.channelCount), &error.rawValue) else { throw error } - encoder = try Opus.Encoder(format: format, - application: application, - customEncoder: opusEncoder) + encoder = opusEncoder // Create custom decoder guard let opusDecoder = opus_custom_decoder_create( customMode, Int32(format.channelCount), &error.rawValue) else { throw error } - decoder = try Opus.Decoder(format: format, - application: application, - customDecoder: opusDecoder) + decoder = opusDecoder } deinit { + opus_encoder_destroy(encoder) + opus_decoder_destroy(decoder) opus_custom_mode_destroy(opusCustomMode) } + + /// + /// Encode a PCM buffer to data using the custom mode configuration and max size + /// + public func encode(_ avData: AVAudioPCMBuffer, + maxCompressedBytes: Int) throws -> Data { + var compressed = Data(capacity: maxCompressedBytes) + compressed.count = try compressed.withUnsafeMutableBytes( + { try encode(avData, to: $0, maxCompressedBytes: maxCompressedBytes) } + ) + return compressed + } + + private func encode(_ input: AVAudioPCMBuffer, + to output: inout [UInt8], + maxCompressedBytes: Int) throws -> Int { + try output.withUnsafeMutableBufferPointer { + try encode(input, to: $0, maxCompressedBytes: maxCompressedBytes) + } + } + + private func encode(_ input: AVAudioPCMBuffer, + to output: UnsafeMutableRawBufferPointer, + maxCompressedBytes: Int) throws -> Int { + let output = UnsafeMutableBufferPointer( + start: output.baseAddress!.bindMemory( + to: UInt8.self, capacity: output.count), + count: output.count) + return try encode(input, to: output, maxCompressedBytes: maxCompressedBytes) + } + + private func encode(_ input: AVAudioPCMBuffer, + to output: UnsafeMutableBufferPointer, + maxCompressedBytes: Int) throws -> Int { + guard input.format.sampleRate == format.sampleRate, + input.format.channelCount == format.channelCount else { + throw Opus.Error.badArgument + } + + switch format.commonFormat { + case .pcmFormatInt16: + let input = UnsafeBufferPointer( + start: input.int16ChannelData![0], + count: Int(input.frameLength * format.channelCount)) + return try encode(input, to: output, maxCompressedBytes: maxCompressedBytes) + + case .pcmFormatFloat32: + let input = UnsafeBufferPointer( + start: input.floatChannelData![0], + count: Int(input.frameLength * format.channelCount)) + return try encode(input, to: output, maxCompressedBytes: maxCompressedBytes) + + default: + throw Opus.Error.badArgument + } + } + + private func encode(_ input: UnsafeBufferPointer, + to output: UnsafeMutableBufferPointer, + maxCompressedBytes: Int) throws -> Int { + let encodedSize = opus_custom_encode( + encoder, + input.baseAddress!, + frameSize, + output.baseAddress!, + Int32(maxCompressedBytes) + ) + + if encodedSize < 0 { + throw Opus.Error(encodedSize) + } + return Int(encodedSize) + } + + private func encode(_ input: UnsafeBufferPointer, + to output: UnsafeMutableBufferPointer, + maxCompressedBytes: Int) throws -> Int { + let encodedSize = opus_custom_encode_float( + encoder, + input.baseAddress!, + Int32(input.count) / Int32(format.channelCount), + output.baseAddress!, + Int32(output.count) + ) + if encodedSize < 0 { + throw Opus.Error(encodedSize) + } + return Int(encodedSize) + } + + + + public func decode(_ data: Data) throws -> AVAudioPCMBuffer { + try data.withUnsafeBytes { + let input = $0.bindMemory(to: UInt8.self) + let sampleCount = opus_decoder_get_nb_samples( + decoder, input.baseAddress!, Int32($0.count) + ) + + let output = AVAudioPCMBuffer( + pcmFormat: format, + frameCapacity: AVAudioFrameCount(sampleCount))! + try decode(input, to: output) + + return output + } + } + + private func decode(_ input: UnsafeBufferPointer, + to output: AVAudioPCMBuffer) throws { + let decodedCount: Int + + switch output.format.commonFormat { + case .pcmFormatInt16: + let output = UnsafeMutableBufferPointer( + start: output.int16ChannelData![0], + count: Int(output.frameCapacity) + ) + decodedCount = try decode(input, to: output) + + case .pcmFormatFloat32: + let output = UnsafeMutableBufferPointer( + start: output.floatChannelData![0], + count: Int(output.frameCapacity) + ) + decodedCount = try decode(input, to: output) + default: + throw Opus.Error.badArgument + } + + if decodedCount < 0 { + throw Opus.Error(decodedCount) + } + output.frameLength = AVAudioFrameCount(decodedCount) + } + + private func decode(_ input: UnsafeBufferPointer, + to output: UnsafeMutableBufferPointer) throws -> Int { + let decodedCount = opus_custom_decode( + decoder, + input.baseAddress!, + Int32(input.count), + output.baseAddress!, + Int32(output.count) + ) + if decodedCount < 0 { + throw Opus.Error(decodedCount) + } + return Int(decodedCount) + } + + private func decode(_ input: UnsafeBufferPointer, + to output: UnsafeMutableBufferPointer) throws -> Int { + let decodedCount = opus_custom_decode_float( + decoder, + input.baseAddress!, + Int32(input.count), + output.baseAddress!, + Int32(output.count) + ) + if decodedCount < 0 { + throw Opus.Error(decodedCount) + } + return Int(decodedCount) + } } } diff --git a/Sources/Opus/Opus.Decoder.swift b/Sources/Opus/Opus.Decoder.swift index 2753c53..4df8aca 100644 --- a/Sources/Opus/Opus.Decoder.swift +++ b/Sources/Opus/Opus.Decoder.swift @@ -7,23 +7,18 @@ public extension Opus { let decoder: OpaquePointer public init(format: AVAudioFormat, - application _: Application = .audio, - customDecoder: OpaquePointer? = nil) throws { + application _: Application = .audio) throws { if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument } self.format = format - // Initialize Opus decoder - var error: Opus.Error = .ok - if let custom = customDecoder { - decoder = custom - } else { - decoder = opus_decoder_create(Int32(format.sampleRate), Int32(format.channelCount), &error.rawValue) - if error != .ok { - throw error - } + // Initialize Opus decoder + var error: Opus.Error = .ok + decoder = opus_decoder_create(Int32(format.sampleRate), Int32(format.channelCount), &error.rawValue) + if error != .ok { + throw error } } diff --git a/Sources/Opus/Opus.Encoder.swift b/Sources/Opus/Opus.Encoder.swift index 6cb4578..15fa5cc 100644 --- a/Sources/Opus/Opus.Encoder.swift +++ b/Sources/Opus/Opus.Encoder.swift @@ -8,8 +8,7 @@ public extension Opus { let encoder: OpaquePointer public init(format: AVAudioFormat, - application: Application = .audio, - customEncoder: OpaquePointer? = nil) throws { + application: Application = .audio) throws { if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument } @@ -19,13 +18,9 @@ public extension Opus { // Initialize Opus encoder var error: Opus.Error = .ok - if let custom = customEncoder { - encoder = custom - } else { - encoder = opus_encoder_create(Int32(format.sampleRate), Int32(format.channelCount), application.rawValue, &error.rawValue) - if error != .ok { - throw error - } + encoder = opus_encoder_create(Int32(format.sampleRate), Int32(format.channelCount), application.rawValue, &error.rawValue) + if error != .ok { + throw error } } From 605b9ec9452cbd80b60cd2511bb5923c92c7ec7e Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Mon, 21 Mar 2022 12:23:36 -0700 Subject: [PATCH 14/37] Fix up encoder bug --- Sources/Opus/Opus.Custom.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index 11c5102..fc15f76 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -131,7 +131,7 @@ public extension Opus { input.baseAddress!, Int32(input.count) / Int32(format.channelCount), output.baseAddress!, - Int32(output.count) + Int32(maxCompressedBytes) ) if encodedSize < 0 { throw Opus.Error(encodedSize) From fefebd7a1c4361f9c457403466a515986a4d2479 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Mon, 21 Mar 2022 12:58:01 -0700 Subject: [PATCH 15/37] Set frame size in encode --- Sources/Opus/Opus.Custom.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index fc15f76..1cef7d1 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -129,7 +129,7 @@ public extension Opus { let encodedSize = opus_custom_encode_float( encoder, input.baseAddress!, - Int32(input.count) / Int32(format.channelCount), + frameSize, output.baseAddress!, Int32(maxCompressedBytes) ) From 3204c1a2a6a07f2acb3ed9b1fd7d2ed4280f80e1 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Mon, 21 Mar 2022 13:08:36 -0700 Subject: [PATCH 16/37] Generalize the ioctl call --- Sources/Opus/Opus.Custom.Jamulus.swift | 50 -------------------------- Sources/Opus/Opus.Custom.swift | 10 ++++++ 2 files changed, 10 insertions(+), 50 deletions(-) delete mode 100644 Sources/Opus/Opus.Custom.Jamulus.swift diff --git a/Sources/Opus/Opus.Custom.Jamulus.swift b/Sources/Opus/Opus.Custom.Jamulus.swift deleted file mode 100644 index 2af18b7..0000000 --- a/Sources/Opus/Opus.Custom.Jamulus.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// File.swift -// -// -// Created by Emlyn Bolton on 2022-03-18. -// - -import Copuswrapper -import Foundation - -public extension Opus.Custom { - - /// - /// Sets up jamulus-specific parts of the custom opus implementation - /// - func configureForJamulus() throws { - var error: Opus.Error = .ok - - // Disable variable bit rates - error.rawValue = opus_custom_encoder_ctl_wrapper( - encoder, - OPUS_SET_VBR_REQUEST, 0) - guard error == .ok else { throw error } - - // Request low latency - error.rawValue = opus_custom_encoder_ctl_wrapper( - encoder, - OPUS_SET_APPLICATION_REQUEST, OPUS_APPLICATION_RESTRICTED_LOWDELAY) - guard error == .ok else { throw error } - - switch frameSize { - case 64: - // Adjust PLC behaviour for better drop out handling - error.rawValue = opus_custom_encoder_ctl_wrapper( - encoder, - OPUS_SET_PACKET_LOSS_PERC_REQUEST, 35) - guard error == .ok else { throw error } - - case 128: - // Set complexity for 128 sample frame size - error.rawValue = opus_custom_encoder_ctl_wrapper( - encoder, - OPUS_SET_COMPLEXITY_REQUEST, 1) - guard error == .ok else { throw error } - - default: - break - } - } -} diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index 1cef7d1..09a4886 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -1,5 +1,6 @@ import AVFoundation import Copus +import Copuswrapper import Foundation public extension Opus { @@ -50,6 +51,15 @@ public extension Opus { opus_custom_mode_destroy(opusCustomMode) } + /// + /// Wrapper onto the opus_custom_encoder_ctl function + public func encoderCtl(request: Int32, value: Int32) -> Opus.Error { + var error: Opus.Error = .ok + error.rawValue = opus_custom_encoder_ctl_wrapper(encoder, + request, value) + return error + } + /// /// Encode a PCM buffer to data using the custom mode configuration and max size /// From b0c9e3b986166af226418588aaea2af2dd3d9a83 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Mon, 21 Mar 2022 13:13:01 -0700 Subject: [PATCH 17/37] make the framesize public --- Sources/Opus/Opus.Custom.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index 09a4886..2b3f9de 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -9,7 +9,7 @@ public extension Opus { let encoder: OpaquePointer let decoder: OpaquePointer private let format: AVAudioFormat - let frameSize: Int32 + public let frameSize: Int32 public init(format: AVAudioFormat, application: Application = .audio, From c898e20cdf122fd863c99d551cec379c372f6d56 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Thu, 31 Mar 2022 08:53:37 -0700 Subject: [PATCH 18/37] Enable sample count to be passed in as a multiplier of frameSize --- Sources/Opus/Opus.Custom.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index 2b3f9de..34254f1 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -151,16 +151,14 @@ public extension Opus { - public func decode(_ data: Data) throws -> AVAudioPCMBuffer { + public func decode(_ data: Data, + sampleMultiplier: Int32) throws -> AVAudioPCMBuffer { try data.withUnsafeBytes { let input = $0.bindMemory(to: UInt8.self) - let sampleCount = opus_decoder_get_nb_samples( - decoder, input.baseAddress!, Int32($0.count) - ) let output = AVAudioPCMBuffer( pcmFormat: format, - frameCapacity: AVAudioFrameCount(sampleCount))! + frameCapacity: AVAudioFrameCount(frameSize * sampleMultiplier))! try decode(input, to: output) return output From 61b6a4ba510d5ab296e015743fada6d6872879ff Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Fri, 1 Apr 2022 13:15:26 -0700 Subject: [PATCH 19/37] Rename method parameter to reflect correct usage --- Sources/Opus/Opus.Custom.swift | 37 +++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index 34254f1..1d228b6 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -4,6 +4,11 @@ import Copuswrapper import Foundation public extension Opus { + + /// + /// Implements a custom opus encoder / decoder. + /// Custom implementations can have non-standard frame sizes + /// class Custom { private let opusCustomMode: OpaquePointer let encoder: OpaquePointer @@ -53,6 +58,10 @@ public extension Opus { /// /// Wrapper onto the opus_custom_encoder_ctl function + /// - Parameter request The Opus CTL to change + /// - Parameter value The value to set it to + /// + /// - Returns Opus.Error code public func encoderCtl(request: Int32, value: Int32) -> Opus.Error { var error: Opus.Error = .ok error.rawValue = opus_custom_encoder_ctl_wrapper(encoder, @@ -64,35 +73,35 @@ public extension Opus { /// Encode a PCM buffer to data using the custom mode configuration and max size /// public func encode(_ avData: AVAudioPCMBuffer, - maxCompressedBytes: Int) throws -> Data { - var compressed = Data(capacity: maxCompressedBytes) + compressedSize: Int) throws -> Data { + var compressed = Data(capacity: compressedSize) compressed.count = try compressed.withUnsafeMutableBytes( - { try encode(avData, to: $0, maxCompressedBytes: maxCompressedBytes) } + { try encode(avData, to: $0, compressedSize: compressedSize) } ) return compressed } private func encode(_ input: AVAudioPCMBuffer, to output: inout [UInt8], - maxCompressedBytes: Int) throws -> Int { + compressedSize: Int) throws -> Int { try output.withUnsafeMutableBufferPointer { - try encode(input, to: $0, maxCompressedBytes: maxCompressedBytes) + try encode(input, to: $0, compressedSize: compressedSize) } } private func encode(_ input: AVAudioPCMBuffer, to output: UnsafeMutableRawBufferPointer, - maxCompressedBytes: Int) throws -> Int { + compressedSize: Int) throws -> Int { let output = UnsafeMutableBufferPointer( start: output.baseAddress!.bindMemory( to: UInt8.self, capacity: output.count), count: output.count) - return try encode(input, to: output, maxCompressedBytes: maxCompressedBytes) + return try encode(input, to: output, compressedSize: compressedSize) } private func encode(_ input: AVAudioPCMBuffer, to output: UnsafeMutableBufferPointer, - maxCompressedBytes: Int) throws -> Int { + compressedSize: Int) throws -> Int { guard input.format.sampleRate == format.sampleRate, input.format.channelCount == format.channelCount else { throw Opus.Error.badArgument @@ -103,13 +112,13 @@ public extension Opus { let input = UnsafeBufferPointer( start: input.int16ChannelData![0], count: Int(input.frameLength * format.channelCount)) - return try encode(input, to: output, maxCompressedBytes: maxCompressedBytes) + return try encode(input, to: output, compressedSize: compressedSize) case .pcmFormatFloat32: let input = UnsafeBufferPointer( start: input.floatChannelData![0], count: Int(input.frameLength * format.channelCount)) - return try encode(input, to: output, maxCompressedBytes: maxCompressedBytes) + return try encode(input, to: output, compressedSize: compressedSize) default: throw Opus.Error.badArgument @@ -118,13 +127,13 @@ public extension Opus { private func encode(_ input: UnsafeBufferPointer, to output: UnsafeMutableBufferPointer, - maxCompressedBytes: Int) throws -> Int { + compressedSize: Int) throws -> Int { let encodedSize = opus_custom_encode( encoder, input.baseAddress!, frameSize, output.baseAddress!, - Int32(maxCompressedBytes) + Int32(compressedSize) ) if encodedSize < 0 { @@ -135,13 +144,13 @@ public extension Opus { private func encode(_ input: UnsafeBufferPointer, to output: UnsafeMutableBufferPointer, - maxCompressedBytes: Int) throws -> Int { + compressedSize: Int) throws -> Int { let encodedSize = opus_custom_encode_float( encoder, input.baseAddress!, frameSize, output.baseAddress!, - Int32(maxCompressedBytes) + Int32(compressedSize) ) if encodedSize < 0 { throw Opus.Error(encodedSize) From 9fa606f12d4d294980fb12354b5bcc4ac44bb2cd Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Sun, 3 Apr 2022 16:21:47 -0700 Subject: [PATCH 20/37] Ensure error code is passed back --- Sources/Opus/Opus.Custom.swift | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index 1d228b6..e5c8366 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -61,12 +61,9 @@ public extension Opus { /// - Parameter request The Opus CTL to change /// - Parameter value The value to set it to /// - /// - Returns Opus.Error code - public func encoderCtl(request: Int32, value: Int32) -> Opus.Error { - var error: Opus.Error = .ok - error.rawValue = opus_custom_encoder_ctl_wrapper(encoder, - request, value) - return error + /// - Returns Opus.Error code raw type + public func encoderCtl(request: Int32, value: Int32) -> Opus.Error.RawValue { + return opus_custom_encoder_ctl_wrapper(encoder, request, value) } /// From 21164e1515cc06e3d542aa2635e5f3fa57f2a8d8 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Sun, 3 Apr 2022 16:37:04 -0700 Subject: [PATCH 21/37] Add explicit return --- Sources/Copuswrapper/variadic-wrapper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Copuswrapper/variadic-wrapper.c b/Sources/Copuswrapper/variadic-wrapper.c index 15503e0..5478110 100644 --- a/Sources/Copuswrapper/variadic-wrapper.c +++ b/Sources/Copuswrapper/variadic-wrapper.c @@ -2,10 +2,10 @@ int opus_custom_encoder_ctl_wrapper(OpusCustomEncoder *OPUS_RESTRICT st, int request, opus_int32 val) { - opus_custom_encoder_ctl(st, request, val); + return opus_custom_encoder_ctl(st, request, val); } int opus_custom_decoder_ctl_wrapper(OpusCustomDecoder *OPUS_RESTRICT st, int request, opus_int32 val) { - opus_custom_decoder_ctl(st, request, val); + return opus_custom_decoder_ctl(st, request, val); } From bada8cf658e3077f5ffd0e394c008a4a78e423ec Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Sat, 9 Apr 2022 18:28:17 -0700 Subject: [PATCH 22/37] Allocate a buffer properly --- Sources/Opus/Opus.Custom.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index e5c8366..92b3734 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -71,7 +71,7 @@ public extension Opus { /// public func encode(_ avData: AVAudioPCMBuffer, compressedSize: Int) throws -> Data { - var compressed = Data(capacity: compressedSize) + var compressed = Data(repeating: 0, count: compressedSize) compressed.count = try compressed.withUnsafeMutableBytes( { try encode(avData, to: $0, compressedSize: compressedSize) } ) From ed39aac72a355ce0e0d6778a0616d97325243d85 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Thu, 14 Apr 2022 15:47:09 -0700 Subject: [PATCH 23/37] Handle the case of null data, aka packet loss --- Package.swift | 2 +- Sources/Opus/Opus.Custom.swift | 34 +++++++++++++++++++++------------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/Package.swift b/Package.swift index ab98add..64acec3 100644 --- a/Package.swift +++ b/Package.swift @@ -91,7 +91,7 @@ let package = Package( .headerSearchPath("silk"), .headerSearchPath("silk/float"), - .define("OPUS_BUILD"), + .define("OPUS_BUILD", to: "1"), .define("CUSTOM_MODES"), .define("VAR_ARRAYS", to: "1"), .define("FLOATING_POINT"), // Enable Opus floating-point mode diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index 92b3734..96b1047 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -100,7 +100,7 @@ public extension Opus { to output: UnsafeMutableBufferPointer, compressedSize: Int) throws -> Int { guard input.format.sampleRate == format.sampleRate, - input.format.channelCount == format.channelCount else { + input.format.channelCount == format.channelCount else { throw Opus.Error.badArgument } @@ -156,8 +156,12 @@ public extension Opus { } - + /// + /// Decode an opus packet + /// If the data is empty, it is treated as a dropped packet + /// The decoder needs the packet size to know what was dropped public func decode(_ data: Data, + compressedPacketSize: Int32, sampleMultiplier: Int32) throws -> AVAudioPCMBuffer { try data.withUnsafeBytes { let input = $0.bindMemory(to: UInt8.self) @@ -165,14 +169,16 @@ public extension Opus { let output = AVAudioPCMBuffer( pcmFormat: format, frameCapacity: AVAudioFrameCount(frameSize * sampleMultiplier))! - try decode(input, to: output) + try decode(input, to: output, packetSize: compressedPacketSize) return output } } private func decode(_ input: UnsafeBufferPointer, - to output: AVAudioPCMBuffer) throws { + to output: AVAudioPCMBuffer, + packetSize: Int32 + ) throws { let decodedCount: Int switch output.format.commonFormat { @@ -181,14 +187,14 @@ public extension Opus { start: output.int16ChannelData![0], count: Int(output.frameCapacity) ) - decodedCount = try decode(input, to: output) + decodedCount = try decode(input, to: output, packetSize: packetSize) case .pcmFormatFloat32: let output = UnsafeMutableBufferPointer( start: output.floatChannelData![0], count: Int(output.frameCapacity) ) - decodedCount = try decode(input, to: output) + decodedCount = try decode(input, to: output, packetSize: packetSize) default: throw Opus.Error.badArgument } @@ -200,11 +206,12 @@ public extension Opus { } private func decode(_ input: UnsafeBufferPointer, - to output: UnsafeMutableBufferPointer) throws -> Int { + to output: UnsafeMutableBufferPointer, + packetSize: Int32) throws -> Int { let decodedCount = opus_custom_decode( decoder, - input.baseAddress!, - Int32(input.count), + input.isEmpty ? nil : input.baseAddress, + packetSize, output.baseAddress!, Int32(output.count) ) @@ -213,13 +220,14 @@ public extension Opus { } return Int(decodedCount) } - + private func decode(_ input: UnsafeBufferPointer, - to output: UnsafeMutableBufferPointer) throws -> Int { + to output: UnsafeMutableBufferPointer, + packetSize: Int32) throws -> Int { let decodedCount = opus_custom_decode_float( decoder, - input.baseAddress!, - Int32(input.count), + input.isEmpty ? nil : input.baseAddress, + packetSize, output.baseAddress!, Int32(output.count) ) From 2c72a7284997b90160f3e458567db59c562ae672 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Mon, 18 Apr 2022 12:31:48 -0700 Subject: [PATCH 24/37] Add documentation; add some safety --- Sources/Opus/Opus.Custom.swift | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index 96b1047..f4f0920 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -9,7 +9,7 @@ public extension Opus { /// Implements a custom opus encoder / decoder. /// Custom implementations can have non-standard frame sizes /// - class Custom { + final class Custom { private let opusCustomMode: OpaquePointer let encoder: OpaquePointer let decoder: OpaquePointer @@ -68,7 +68,9 @@ public extension Opus { /// /// Encode a PCM buffer to data using the custom mode configuration and max size - /// + /// - parameter avData Audio data to compress + /// - parameter compressedSize Opus packet size to compress to + /// - Returns Data containing the Opus packet public func encode(_ avData: AVAudioPCMBuffer, compressedSize: Int) throws -> Data { var compressed = Data(repeating: 0, count: compressedSize) @@ -159,11 +161,18 @@ public extension Opus { /// /// Decode an opus packet /// If the data is empty, it is treated as a dropped packet - /// The decoder needs the packet size to know what was dropped + /// - Parameter data Compressed data + /// - Parameter compressedPacketSize Number of bytes of data + /// - Parameter sampleMultiplier Frame size multiplier if greater than one + /// - Returns Uncompressed audio buffer public func decode(_ data: Data, compressedPacketSize: Int32, - sampleMultiplier: Int32) throws -> AVAudioPCMBuffer { - try data.withUnsafeBytes { + sampleMultiplier: Int32 = 1) throws -> AVAudioPCMBuffer { + guard data.isEmpty || data.count == compressedPacketSize else { + throw Opus.Error.bufferTooSmall + } + + return try data.withUnsafeBytes { let input = $0.bindMemory(to: UInt8.self) let output = AVAudioPCMBuffer( From b41d414268b9ee82c50f961e197f11da6acef344 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Tue, 19 Apr 2022 12:11:16 -0700 Subject: [PATCH 25/37] Tidy some changes prior to PR back to fork source --- Package.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index 64acec3..c4ed035 100644 --- a/Package.swift +++ b/Package.swift @@ -31,9 +31,9 @@ let package = Package( exclude: [ "AUTHORS", "autogen.sh", - "celt/arm", "celt_headers.mk", "celt_sources.mk", + "celt/arm", "celt/dump_modes", "celt/meson.build", "celt/opus_custom_demo.c", @@ -91,7 +91,7 @@ let package = Package( .headerSearchPath("silk"), .headerSearchPath("silk/float"), - .define("OPUS_BUILD", to: "1"), + .define("OPUS_BUILD"), .define("CUSTOM_MODES"), .define("VAR_ARRAYS", to: "1"), .define("FLOATING_POINT"), // Enable Opus floating-point mode From 40fb047e8bcb5d739824256c6fd33e1a2d1b095d Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Tue, 19 Apr 2022 12:14:30 -0700 Subject: [PATCH 26/37] More whitespace formatting --- Package.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Package.swift b/Package.swift index c4ed035..fd55fd6 100644 --- a/Package.swift +++ b/Package.swift @@ -110,14 +110,14 @@ let package = Package( .define("HAVE_UNISTD_H", to: "1"), ] ), - .target( - name: "Copuswrapper", - dependencies: ["Copus"], - publicHeadersPath: "include", - cSettings: [ - .headerSearchPath(".") - ] - ), + .target( + name: "Copuswrapper", + dependencies: ["Copus"], + publicHeadersPath: "include", + cSettings: [ + .headerSearchPath(".") + ] + ), .target( name: "Opus", dependencies: ["Copus", "Copuswrapper"] From e3788e30b4feae2075d12be83046bede110f58b4 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Tue, 19 Apr 2022 15:35:20 -0700 Subject: [PATCH 27/37] Update submodule to correct (master branch version) --- Sources/Copus | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Copus b/Sources/Copus index 61747bc..ccaaffa 160000 --- a/Sources/Copus +++ b/Sources/Copus @@ -1 +1 @@ -Subproject commit 61747bc6ec728de69d54db6ece90ad4617f059b8 +Subproject commit ccaaffa9a3ee427e9401c4dcf6462e378d9a4694 From 8b656b36c41601beee4f578b6d204201dbc74ff5 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Tue, 19 Apr 2022 15:40:25 -0700 Subject: [PATCH 28/37] Apply swiftformat rules --- Package.swift | 4 +- Sources/Opus/Opus.Custom.swift | 502 ++++++++++++++++---------------- Sources/Opus/Opus.Decoder.swift | 17 +- Sources/Opus/Opus.Encoder.swift | 11 +- 4 files changed, 276 insertions(+), 258 deletions(-) diff --git a/Package.swift b/Package.swift index fd55fd6..688eda7 100644 --- a/Package.swift +++ b/Package.swift @@ -110,12 +110,12 @@ let package = Package( .define("HAVE_UNISTD_H", to: "1"), ] ), - .target( + .target( name: "Copuswrapper", dependencies: ["Copus"], publicHeadersPath: "include", cSettings: [ - .headerSearchPath(".") + .headerSearchPath("."), ] ), .target( diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index f4f0920..51865fe 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -4,247 +4,263 @@ import Copuswrapper import Foundation public extension Opus { - - /// - /// Implements a custom opus encoder / decoder. - /// Custom implementations can have non-standard frame sizes - /// - final class Custom { - private let opusCustomMode: OpaquePointer - let encoder: OpaquePointer - let decoder: OpaquePointer - private let format: AVAudioFormat - public let frameSize: Int32 - - public init(format: AVAudioFormat, - application: Application = .audio, - frameSize: UInt32 = 128) throws { - if !format.isValidOpusPCMFormat { - throw Opus.Error.badArgument - } - self.format = format - self.frameSize = Int32(frameSize) - - var error: Opus.Error = .ok - - // Create custom parameters - guard let customMode = opus_custom_mode_create( - Int32(format.sampleRate), - Int32(frameSize), - &error.rawValue) else { throw error } - opusCustomMode = customMode - - // Create custom encoder - guard let opusEncoder = opus_custom_encoder_create( - customMode, - Int32(format.channelCount), - &error.rawValue) else { throw error } - - encoder = opusEncoder - - // Create custom decoder - guard let opusDecoder = opus_custom_decoder_create( - customMode, - Int32(format.channelCount), - &error.rawValue) else { throw error } - decoder = opusDecoder - } - - deinit { - opus_encoder_destroy(encoder) - opus_decoder_destroy(decoder) - opus_custom_mode_destroy(opusCustomMode) - } - - /// - /// Wrapper onto the opus_custom_encoder_ctl function - /// - Parameter request The Opus CTL to change - /// - Parameter value The value to set it to - /// - /// - Returns Opus.Error code raw type - public func encoderCtl(request: Int32, value: Int32) -> Opus.Error.RawValue { - return opus_custom_encoder_ctl_wrapper(encoder, request, value) - } - - /// - /// Encode a PCM buffer to data using the custom mode configuration and max size - /// - parameter avData Audio data to compress - /// - parameter compressedSize Opus packet size to compress to - /// - Returns Data containing the Opus packet - public func encode(_ avData: AVAudioPCMBuffer, - compressedSize: Int) throws -> Data { - var compressed = Data(repeating: 0, count: compressedSize) - compressed.count = try compressed.withUnsafeMutableBytes( - { try encode(avData, to: $0, compressedSize: compressedSize) } - ) - return compressed - } - - private func encode(_ input: AVAudioPCMBuffer, - to output: inout [UInt8], - compressedSize: Int) throws -> Int { - try output.withUnsafeMutableBufferPointer { - try encode(input, to: $0, compressedSize: compressedSize) - } - } - - private func encode(_ input: AVAudioPCMBuffer, - to output: UnsafeMutableRawBufferPointer, - compressedSize: Int) throws -> Int { - let output = UnsafeMutableBufferPointer( - start: output.baseAddress!.bindMemory( - to: UInt8.self, capacity: output.count), - count: output.count) - return try encode(input, to: output, compressedSize: compressedSize) - } - - private func encode(_ input: AVAudioPCMBuffer, - to output: UnsafeMutableBufferPointer, - compressedSize: Int) throws -> Int { - guard input.format.sampleRate == format.sampleRate, - input.format.channelCount == format.channelCount else { - throw Opus.Error.badArgument - } - - switch format.commonFormat { - case .pcmFormatInt16: - let input = UnsafeBufferPointer( - start: input.int16ChannelData![0], - count: Int(input.frameLength * format.channelCount)) - return try encode(input, to: output, compressedSize: compressedSize) - - case .pcmFormatFloat32: - let input = UnsafeBufferPointer( - start: input.floatChannelData![0], - count: Int(input.frameLength * format.channelCount)) - return try encode(input, to: output, compressedSize: compressedSize) - - default: - throw Opus.Error.badArgument - } - } - - private func encode(_ input: UnsafeBufferPointer, - to output: UnsafeMutableBufferPointer, - compressedSize: Int) throws -> Int { - let encodedSize = opus_custom_encode( - encoder, - input.baseAddress!, - frameSize, - output.baseAddress!, - Int32(compressedSize) - ) - - if encodedSize < 0 { - throw Opus.Error(encodedSize) - } - return Int(encodedSize) - } - - private func encode(_ input: UnsafeBufferPointer, - to output: UnsafeMutableBufferPointer, - compressedSize: Int) throws -> Int { - let encodedSize = opus_custom_encode_float( - encoder, - input.baseAddress!, - frameSize, - output.baseAddress!, - Int32(compressedSize) - ) - if encodedSize < 0 { - throw Opus.Error(encodedSize) - } - return Int(encodedSize) - } - - - /// - /// Decode an opus packet - /// If the data is empty, it is treated as a dropped packet - /// - Parameter data Compressed data - /// - Parameter compressedPacketSize Number of bytes of data - /// - Parameter sampleMultiplier Frame size multiplier if greater than one - /// - Returns Uncompressed audio buffer - public func decode(_ data: Data, - compressedPacketSize: Int32, - sampleMultiplier: Int32 = 1) throws -> AVAudioPCMBuffer { - guard data.isEmpty || data.count == compressedPacketSize else { - throw Opus.Error.bufferTooSmall - } - - return try data.withUnsafeBytes { - let input = $0.bindMemory(to: UInt8.self) - - let output = AVAudioPCMBuffer( - pcmFormat: format, - frameCapacity: AVAudioFrameCount(frameSize * sampleMultiplier))! - try decode(input, to: output, packetSize: compressedPacketSize) - - return output - } - } - - private func decode(_ input: UnsafeBufferPointer, - to output: AVAudioPCMBuffer, - packetSize: Int32 - ) throws { - let decodedCount: Int - - switch output.format.commonFormat { - case .pcmFormatInt16: - let output = UnsafeMutableBufferPointer( - start: output.int16ChannelData![0], - count: Int(output.frameCapacity) - ) - decodedCount = try decode(input, to: output, packetSize: packetSize) - - case .pcmFormatFloat32: - let output = UnsafeMutableBufferPointer( - start: output.floatChannelData![0], - count: Int(output.frameCapacity) - ) - decodedCount = try decode(input, to: output, packetSize: packetSize) - default: - throw Opus.Error.badArgument - } - - if decodedCount < 0 { - throw Opus.Error(decodedCount) - } - output.frameLength = AVAudioFrameCount(decodedCount) - } - - private func decode(_ input: UnsafeBufferPointer, - to output: UnsafeMutableBufferPointer, - packetSize: Int32) throws -> Int { - let decodedCount = opus_custom_decode( - decoder, - input.isEmpty ? nil : input.baseAddress, - packetSize, - output.baseAddress!, - Int32(output.count) - ) - if decodedCount < 0 { - throw Opus.Error(decodedCount) - } - return Int(decodedCount) - } - - private func decode(_ input: UnsafeBufferPointer, - to output: UnsafeMutableBufferPointer, - packetSize: Int32) throws -> Int { - let decodedCount = opus_custom_decode_float( - decoder, - input.isEmpty ? nil : input.baseAddress, - packetSize, - output.baseAddress!, - Int32(output.count) - ) - if decodedCount < 0 { - throw Opus.Error(decodedCount) - } - return Int(decodedCount) - } - } -} + /// + /// Implements a custom opus encoder / decoder. + /// Custom implementations can have non-standard frame sizes + /// + final class Custom { + private let opusCustomMode: OpaquePointer + let encoder: OpaquePointer + let decoder: OpaquePointer + private let format: AVAudioFormat + public let frameSize: Int32 + + public init(format: AVAudioFormat, + application _: Application = .audio, + frameSize: UInt32 = 128) throws + { + if !format.isValidOpusPCMFormat { + throw Opus.Error.badArgument + } + self.format = format + self.frameSize = Int32(frameSize) + + var error: Opus.Error = .ok + + // Create custom parameters + guard let customMode = opus_custom_mode_create( + Int32(format.sampleRate), + Int32(frameSize), + &error.rawValue + ) else { throw error } + opusCustomMode = customMode + + // Create custom encoder + guard let opusEncoder = opus_custom_encoder_create( + customMode, + Int32(format.channelCount), + &error.rawValue + ) else { throw error } + + encoder = opusEncoder + + // Create custom decoder + guard let opusDecoder = opus_custom_decoder_create( + customMode, + Int32(format.channelCount), + &error.rawValue + ) else { throw error } + decoder = opusDecoder + } + + deinit { + opus_encoder_destroy(encoder) + opus_decoder_destroy(decoder) + opus_custom_mode_destroy(opusCustomMode) + } + + /// + /// Wrapper onto the opus_custom_encoder_ctl function + /// - Parameter request The Opus CTL to change + /// - Parameter value The value to set it to + /// + /// - Returns Opus.Error code raw type + public func encoderCtl(request: Int32, value: Int32) -> Opus.Error.RawValue { + opus_custom_encoder_ctl_wrapper(encoder, request, value) + } + + /// + /// Encode a PCM buffer to data using the custom mode configuration and max size + /// - parameter avData Audio data to compress + /// - parameter compressedSize Opus packet size to compress to + /// - Returns Data containing the Opus packet + public func encode(_ avData: AVAudioPCMBuffer, + compressedSize: Int) throws -> Data + { + var compressed = Data(repeating: 0, count: compressedSize) + compressed.count = try compressed.withUnsafeMutableBytes( + { try encode(avData, to: $0, compressedSize: compressedSize) } + ) + return compressed + } + + private func encode(_ input: AVAudioPCMBuffer, + to output: inout [UInt8], + compressedSize: Int) throws -> Int + { + try output.withUnsafeMutableBufferPointer { + try encode(input, to: $0, compressedSize: compressedSize) + } + } + + private func encode(_ input: AVAudioPCMBuffer, + to output: UnsafeMutableRawBufferPointer, + compressedSize: Int) throws -> Int + { + let output = UnsafeMutableBufferPointer( + start: output.baseAddress!.bindMemory( + to: UInt8.self, capacity: output.count + ), + count: output.count + ) + return try encode(input, to: output, compressedSize: compressedSize) + } + + private func encode(_ input: AVAudioPCMBuffer, + to output: UnsafeMutableBufferPointer, + compressedSize: Int) throws -> Int + { + guard input.format.sampleRate == format.sampleRate, + input.format.channelCount == format.channelCount + else { + throw Opus.Error.badArgument + } + + switch format.commonFormat { + case .pcmFormatInt16: + let input = UnsafeBufferPointer( + start: input.int16ChannelData![0], + count: Int(input.frameLength * format.channelCount) + ) + return try encode(input, to: output, compressedSize: compressedSize) + + case .pcmFormatFloat32: + let input = UnsafeBufferPointer( + start: input.floatChannelData![0], + count: Int(input.frameLength * format.channelCount) + ) + return try encode(input, to: output, compressedSize: compressedSize) + default: + throw Opus.Error.badArgument + } + } + + private func encode(_ input: UnsafeBufferPointer, + to output: UnsafeMutableBufferPointer, + compressedSize: Int) throws -> Int + { + let encodedSize = opus_custom_encode( + encoder, + input.baseAddress!, + frameSize, + output.baseAddress!, + Int32(compressedSize) + ) + + if encodedSize < 0 { + throw Opus.Error(encodedSize) + } + return Int(encodedSize) + } + + private func encode(_ input: UnsafeBufferPointer, + to output: UnsafeMutableBufferPointer, + compressedSize: Int) throws -> Int + { + let encodedSize = opus_custom_encode_float( + encoder, + input.baseAddress!, + frameSize, + output.baseAddress!, + Int32(compressedSize) + ) + if encodedSize < 0 { + throw Opus.Error(encodedSize) + } + return Int(encodedSize) + } + + /// + /// Decode an opus packet + /// If the data is empty, it is treated as a dropped packet + /// - Parameter data Compressed data + /// - Parameter compressedPacketSize Number of bytes of data + /// - Parameter sampleMultiplier Frame size multiplier if greater than one + /// - Returns Uncompressed audio buffer + public func decode(_ data: Data, + compressedPacketSize: Int32, + sampleMultiplier: Int32 = 1) throws -> AVAudioPCMBuffer + { + guard data.isEmpty || data.count == compressedPacketSize else { + throw Opus.Error.bufferTooSmall + } + + return try data.withUnsafeBytes { + let input = $0.bindMemory(to: UInt8.self) + + let output = AVAudioPCMBuffer( + pcmFormat: format, + frameCapacity: AVAudioFrameCount(frameSize * sampleMultiplier) + )! + try decode(input, to: output, packetSize: compressedPacketSize) + + return output + } + } + + private func decode(_ input: UnsafeBufferPointer, + to output: AVAudioPCMBuffer, + packetSize: Int32) throws + { + let decodedCount: Int + + switch output.format.commonFormat { + case .pcmFormatInt16: + let output = UnsafeMutableBufferPointer( + start: output.int16ChannelData![0], + count: Int(output.frameCapacity) + ) + decodedCount = try decode(input, to: output, packetSize: packetSize) + + case .pcmFormatFloat32: + let output = UnsafeMutableBufferPointer( + start: output.floatChannelData![0], + count: Int(output.frameCapacity) + ) + decodedCount = try decode(input, to: output, packetSize: packetSize) + default: + throw Opus.Error.badArgument + } + + if decodedCount < 0 { + throw Opus.Error(decodedCount) + } + output.frameLength = AVAudioFrameCount(decodedCount) + } + + private func decode(_ input: UnsafeBufferPointer, + to output: UnsafeMutableBufferPointer, + packetSize: Int32) throws -> Int + { + let decodedCount = opus_custom_decode( + decoder, + input.isEmpty ? nil : input.baseAddress, + packetSize, + output.baseAddress!, + Int32(output.count) + ) + if decodedCount < 0 { + throw Opus.Error(decodedCount) + } + return Int(decodedCount) + } + + private func decode(_ input: UnsafeBufferPointer, + to output: UnsafeMutableBufferPointer, + packetSize: Int32) throws -> Int + { + let decodedCount = opus_custom_decode_float( + decoder, + input.isEmpty ? nil : input.baseAddress, + packetSize, + output.baseAddress!, + Int32(output.count) + ) + if decodedCount < 0 { + throw Opus.Error(decodedCount) + } + return Int(decodedCount) + } + } +} diff --git a/Sources/Opus/Opus.Decoder.swift b/Sources/Opus/Opus.Decoder.swift index 7e0eb7b..3842f92 100644 --- a/Sources/Opus/Opus.Decoder.swift +++ b/Sources/Opus/Opus.Decoder.swift @@ -7,20 +7,21 @@ public extension Opus { let decoder: OpaquePointer public init(format: AVAudioFormat, - application _: Application = .audio) throws { + application _: Application = .audio) throws + { if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument } self.format = format - // Initialize Opus decoder - var error: Opus.Error = .ok - decoder = opus_decoder_create(Int32(format.sampleRate), Int32(format.channelCount), &error.rawValue) - if error != .ok { - throw error - } - } + // Initialize Opus decoder + var error: Opus.Error = .ok + decoder = opus_decoder_create(Int32(format.sampleRate), Int32(format.channelCount), &error.rawValue) + if error != .ok { + throw error + } + } deinit { opus_decoder_destroy(decoder) diff --git a/Sources/Opus/Opus.Encoder.swift b/Sources/Opus/Opus.Encoder.swift index 15fa5cc..82b12eb 100644 --- a/Sources/Opus/Opus.Encoder.swift +++ b/Sources/Opus/Opus.Encoder.swift @@ -8,7 +8,8 @@ public extension Opus { let encoder: OpaquePointer public init(format: AVAudioFormat, - application: Application = .audio) throws { + application: Application = .audio) throws + { if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument } @@ -18,10 +19,10 @@ public extension Opus { // Initialize Opus encoder var error: Opus.Error = .ok - encoder = opus_encoder_create(Int32(format.sampleRate), Int32(format.channelCount), application.rawValue, &error.rawValue) - if error != .ok { - throw error - } + encoder = opus_encoder_create(Int32(format.sampleRate), Int32(format.channelCount), application.rawValue, &error.rawValue) + if error != .ok { + throw error + } } deinit { From e7cb649a391069ce08e22604afd6d65e671700d1 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Tue, 19 Apr 2022 15:45:15 -0700 Subject: [PATCH 29/37] Revert swiftformat changes that cause changes to master --- Sources/Opus/Opus.Decoder.swift | 4 ++-- Sources/Opus/Opus.Encoder.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/Opus/Opus.Decoder.swift b/Sources/Opus/Opus.Decoder.swift index 3842f92..1ae673a 100644 --- a/Sources/Opus/Opus.Decoder.swift +++ b/Sources/Opus/Opus.Decoder.swift @@ -6,8 +6,8 @@ public extension Opus { let format: AVAudioFormat let decoder: OpaquePointer - public init(format: AVAudioFormat, - application _: Application = .audio) throws + // TODO: throw an error if format is unsupported + public init(format: AVAudioFormat, application _: Application = .audio) throws { if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument diff --git a/Sources/Opus/Opus.Encoder.swift b/Sources/Opus/Opus.Encoder.swift index 82b12eb..100bce9 100644 --- a/Sources/Opus/Opus.Encoder.swift +++ b/Sources/Opus/Opus.Encoder.swift @@ -7,8 +7,8 @@ public extension Opus { let application: Application let encoder: OpaquePointer - public init(format: AVAudioFormat, - application: Application = .audio) throws + // TODO: throw an error if format is unsupported + public init(format: AVAudioFormat, application: Application = .audio) throws { if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument From a7f8272f680fee3ef8afc366c0030258a1cf7fc2 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Tue, 19 Apr 2022 15:45:59 -0700 Subject: [PATCH 30/37] One more swiftformat change revert --- Sources/Opus/Opus.Decoder.swift | 3 +-- Sources/Opus/Opus.Encoder.swift | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Sources/Opus/Opus.Decoder.swift b/Sources/Opus/Opus.Decoder.swift index 1ae673a..8452403 100644 --- a/Sources/Opus/Opus.Decoder.swift +++ b/Sources/Opus/Opus.Decoder.swift @@ -7,8 +7,7 @@ public extension Opus { let decoder: OpaquePointer // TODO: throw an error if format is unsupported - public init(format: AVAudioFormat, application _: Application = .audio) throws - { + public init(format: AVAudioFormat, application _: Application = .audio) throws { if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument } diff --git a/Sources/Opus/Opus.Encoder.swift b/Sources/Opus/Opus.Encoder.swift index 100bce9..37dac29 100644 --- a/Sources/Opus/Opus.Encoder.swift +++ b/Sources/Opus/Opus.Encoder.swift @@ -8,8 +8,7 @@ public extension Opus { let encoder: OpaquePointer // TODO: throw an error if format is unsupported - public init(format: AVAudioFormat, application: Application = .audio) throws - { + public init(format: AVAudioFormat, application: Application = .audio) throws { if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument } From a5b29aa8db28db7146ac278dbe25bcd303f3fd91 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Wed, 20 Apr 2022 09:52:00 -0700 Subject: [PATCH 31/37] Change return type on ctl wrapper method --- Sources/Opus/Opus.Custom.swift | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index 51865fe..d73a0c9 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -61,12 +61,15 @@ public extension Opus { /// /// Wrapper onto the opus_custom_encoder_ctl function + /// https://www.opus-codec.org/docs/opus_api-1.3.1/group__opus__encoderctls.html /// - Parameter request The Opus CTL to change /// - Parameter value The value to set it to /// - /// - Returns Opus.Error code raw type - public func encoderCtl(request: Int32, value: Int32) -> Opus.Error.RawValue { - opus_custom_encoder_ctl_wrapper(encoder, request, value) + /// - Returns Opus.Error code + public func encoderCtl(request: Int32, value: Int32) -> Opus.Error { + Opus.Error( + rawValue: opus_custom_encoder_ctl_wrapper(encoder, request, value) + ) } /// From 712b0ff1b1dbcd17a58b48e815fa0275564bfc52 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Wed, 20 Apr 2022 12:56:36 -0700 Subject: [PATCH 32/37] Merge opus custom with existing en/de-coders --- Sources/Opus/Opus.Custom.swift | 203 +++----------------------------- Sources/Opus/Opus.Decoder.swift | 120 ++++++++++++++----- Sources/Opus/Opus.Encoder.swift | 121 +++++++++++++++---- 3 files changed, 203 insertions(+), 241 deletions(-) diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index d73a0c9..4798fb7 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -10,8 +10,8 @@ public extension Opus { /// final class Custom { private let opusCustomMode: OpaquePointer - let encoder: OpaquePointer - let decoder: OpaquePointer + let encoder: Opus.Encoder + let decoder: Opus.Decoder private let format: AVAudioFormat public let frameSize: Int32 @@ -36,26 +36,16 @@ public extension Opus { opusCustomMode = customMode // Create custom encoder - guard let opusEncoder = opus_custom_encoder_create( - customMode, - Int32(format.channelCount), - &error.rawValue - ) else { throw error } - - encoder = opusEncoder - + encoder = try Opus.Encoder(customOpus: opusCustomMode, + format: format, + frameSize: frameSize) // Create custom decoder - guard let opusDecoder = opus_custom_decoder_create( - customMode, - Int32(format.channelCount), - &error.rawValue - ) else { throw error } - decoder = opusDecoder + decoder = try Opus.Decoder(customOpus: opusCustomMode, + format: format, + frameSize: frameSize) } deinit { - opus_encoder_destroy(encoder) - opus_decoder_destroy(decoder) opus_custom_mode_destroy(opusCustomMode) } @@ -68,7 +58,7 @@ public extension Opus { /// - Returns Opus.Error code public func encoderCtl(request: Int32, value: Int32) -> Opus.Error { Opus.Error( - rawValue: opus_custom_encoder_ctl_wrapper(encoder, request, value) + rawValue: opus_custom_encoder_ctl_wrapper(encoder.encoder, request, value) ) } @@ -78,100 +68,8 @@ public extension Opus { /// - parameter compressedSize Opus packet size to compress to /// - Returns Data containing the Opus packet public func encode(_ avData: AVAudioPCMBuffer, - compressedSize: Int) throws -> Data - { - var compressed = Data(repeating: 0, count: compressedSize) - compressed.count = try compressed.withUnsafeMutableBytes( - { try encode(avData, to: $0, compressedSize: compressedSize) } - ) - return compressed - } - - private func encode(_ input: AVAudioPCMBuffer, - to output: inout [UInt8], - compressedSize: Int) throws -> Int - { - try output.withUnsafeMutableBufferPointer { - try encode(input, to: $0, compressedSize: compressedSize) - } - } - - private func encode(_ input: AVAudioPCMBuffer, - to output: UnsafeMutableRawBufferPointer, - compressedSize: Int) throws -> Int - { - let output = UnsafeMutableBufferPointer( - start: output.baseAddress!.bindMemory( - to: UInt8.self, capacity: output.count - ), - count: output.count - ) - return try encode(input, to: output, compressedSize: compressedSize) - } - - private func encode(_ input: AVAudioPCMBuffer, - to output: UnsafeMutableBufferPointer, - compressedSize: Int) throws -> Int - { - guard input.format.sampleRate == format.sampleRate, - input.format.channelCount == format.channelCount - else { - throw Opus.Error.badArgument - } - - switch format.commonFormat { - case .pcmFormatInt16: - let input = UnsafeBufferPointer( - start: input.int16ChannelData![0], - count: Int(input.frameLength * format.channelCount) - ) - return try encode(input, to: output, compressedSize: compressedSize) - - case .pcmFormatFloat32: - let input = UnsafeBufferPointer( - start: input.floatChannelData![0], - count: Int(input.frameLength * format.channelCount) - ) - return try encode(input, to: output, compressedSize: compressedSize) - - default: - throw Opus.Error.badArgument - } - } - - private func encode(_ input: UnsafeBufferPointer, - to output: UnsafeMutableBufferPointer, - compressedSize: Int) throws -> Int - { - let encodedSize = opus_custom_encode( - encoder, - input.baseAddress!, - frameSize, - output.baseAddress!, - Int32(compressedSize) - ) - - if encodedSize < 0 { - throw Opus.Error(encodedSize) - } - return Int(encodedSize) - } - - private func encode(_ input: UnsafeBufferPointer, - to output: UnsafeMutableBufferPointer, - compressedSize: Int) throws -> Int - { - let encodedSize = opus_custom_encode_float( - encoder, - input.baseAddress!, - frameSize, - output.baseAddress!, - Int32(compressedSize) - ) - if encodedSize < 0 { - throw Opus.Error(encodedSize) - } - return Int(encodedSize) + compressedSize: Int) throws -> Data { + return try encoder.encode(avData, compressedSize: compressedSize) } /// @@ -188,82 +86,9 @@ public extension Opus { guard data.isEmpty || data.count == compressedPacketSize else { throw Opus.Error.bufferTooSmall } - - return try data.withUnsafeBytes { - let input = $0.bindMemory(to: UInt8.self) - - let output = AVAudioPCMBuffer( - pcmFormat: format, - frameCapacity: AVAudioFrameCount(frameSize * sampleMultiplier) - )! - try decode(input, to: output, packetSize: compressedPacketSize) - - return output - } - } - - private func decode(_ input: UnsafeBufferPointer, - to output: AVAudioPCMBuffer, - packetSize: Int32) throws - { - let decodedCount: Int - - switch output.format.commonFormat { - case .pcmFormatInt16: - let output = UnsafeMutableBufferPointer( - start: output.int16ChannelData![0], - count: Int(output.frameCapacity) - ) - decodedCount = try decode(input, to: output, packetSize: packetSize) - - case .pcmFormatFloat32: - let output = UnsafeMutableBufferPointer( - start: output.floatChannelData![0], - count: Int(output.frameCapacity) - ) - decodedCount = try decode(input, to: output, packetSize: packetSize) - default: - throw Opus.Error.badArgument - } - - if decodedCount < 0 { - throw Opus.Error(decodedCount) - } - output.frameLength = AVAudioFrameCount(decodedCount) - } - - private func decode(_ input: UnsafeBufferPointer, - to output: UnsafeMutableBufferPointer, - packetSize: Int32) throws -> Int - { - let decodedCount = opus_custom_decode( - decoder, - input.isEmpty ? nil : input.baseAddress, - packetSize, - output.baseAddress!, - Int32(output.count) - ) - if decodedCount < 0 { - throw Opus.Error(decodedCount) - } - return Int(decodedCount) - } - - private func decode(_ input: UnsafeBufferPointer, - to output: UnsafeMutableBufferPointer, - packetSize: Int32) throws -> Int - { - let decodedCount = opus_custom_decode_float( - decoder, - input.isEmpty ? nil : input.baseAddress, - packetSize, - output.baseAddress!, - Int32(output.count) - ) - if decodedCount < 0 { - throw Opus.Error(decodedCount) - } - return Int(decodedCount) + return try decoder.decode(data, + compressedPacketSize: compressedPacketSize, + sampleMultiplier: sampleMultiplier) } } } diff --git a/Sources/Opus/Opus.Decoder.swift b/Sources/Opus/Opus.Decoder.swift index 8452403..35376cf 100644 --- a/Sources/Opus/Opus.Decoder.swift +++ b/Sources/Opus/Opus.Decoder.swift @@ -5,9 +5,10 @@ public extension Opus { class Decoder { let format: AVAudioFormat let decoder: OpaquePointer + let customFrameSize: Int32? - // TODO: throw an error if format is unsupported public init(format: AVAudioFormat, application _: Application = .audio) throws { + customFrameSize = nil if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument } @@ -22,6 +23,27 @@ public extension Opus { } } + public init(customOpus: OpaquePointer, + format: AVAudioFormat, + frameSize: UInt32) throws + { + customFrameSize = Int32(frameSize) + if !format.isValidOpusPCMFormat { + throw Opus.Error.badArgument + } + + self.format = format + + // Initialize Opus decoder + var error: Opus.Error = .ok + decoder = opus_custom_decoder_create(customOpus, + Int32(format.channelCount), + &error.rawValue) + if error != .ok { + throw error + } + } + deinit { opus_decoder_destroy(decoder) } @@ -38,28 +60,42 @@ public extension Opus { // MARK: Public decode methods public extension Opus.Decoder { - func decode(_ input: Data) throws -> AVAudioPCMBuffer { + func decode(_ input: Data, + compressedPacketSize: Int32? = nil, + sampleMultiplier: Int32 = 1) throws -> AVAudioPCMBuffer + { try input.withUnsafeBytes { + var output: AVAudioPCMBuffer let input = $0.bindMemory(to: UInt8.self) - let sampleCount = opus_decoder_get_nb_samples(decoder, input.baseAddress!, Int32($0.count)) - if sampleCount < 0 { - throw Opus.Error(sampleCount) + if compressedPacketSize != nil, let frameSize = customFrameSize { + output = AVAudioPCMBuffer( + pcmFormat: format, + frameCapacity: AVAudioFrameCount(frameSize * sampleMultiplier) + )! + } else { + let sampleCount = opus_decoder_get_nb_samples(decoder, input.baseAddress!, Int32($0.count)) + if sampleCount < 0 { + throw Opus.Error(sampleCount) + } + output = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: AVAudioFrameCount(sampleCount))! } - let output = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: AVAudioFrameCount(sampleCount))! - try decode(input, to: output) + + try decode(input, to: output, packetSize: compressedPacketSize) return output } } - func decode(_ input: UnsafeBufferPointer, to output: AVAudioPCMBuffer) throws { + func decode(_ input: UnsafeBufferPointer, to output: AVAudioPCMBuffer, + packetSize: Int32? = nil) throws + { let decodedCount: Int switch output.format.commonFormat { case .pcmFormatInt16: let output = UnsafeMutableBufferPointer(start: output.int16ChannelData![0], count: Int(output.frameCapacity)) - decodedCount = try decode(input, to: output) + decodedCount = try decode(input, to: output, packetSize: packetSize) case .pcmFormatFloat32: let output = UnsafeMutableBufferPointer(start: output.floatChannelData![0], count: Int(output.frameCapacity)) - decodedCount = try decode(input, to: output) + decodedCount = try decode(input, to: output, packetSize: packetSize) default: throw Opus.Error.badArgument } @@ -73,30 +109,58 @@ public extension Opus.Decoder { // MARK: Private decode methods extension Opus.Decoder { - private func decode(_ input: UnsafeBufferPointer, to output: UnsafeMutableBufferPointer) throws -> Int { - let decodedCount = opus_decode( - decoder, - input.baseAddress!, - Int32(input.count), - output.baseAddress!, - Int32(output.count), - 0 - ) + private func decode(_ input: UnsafeBufferPointer, + to output: UnsafeMutableBufferPointer, + packetSize: Int32?) throws -> Int + { + var decodedCount: Int32 = 0 + if let size = packetSize { + decodedCount = opus_custom_decode( + decoder, + input.isEmpty ? nil : input.baseAddress, + size, + output.baseAddress!, + Int32(output.count) + ) + } else { + decodedCount = opus_decode( + decoder, + input.isEmpty ? nil : input.baseAddress, + Int32(input.count), + output.baseAddress!, + Int32(output.count), + 0 + ) + } if decodedCount < 0 { throw Opus.Error(decodedCount) } return Int(decodedCount) } - private func decode(_ input: UnsafeBufferPointer, to output: UnsafeMutableBufferPointer) throws -> Int { - let decodedCount = opus_decode_float( - decoder, - input.baseAddress!, - Int32(input.count), - output.baseAddress!, - Int32(output.count), - 0 - ) + private func decode(_ input: UnsafeBufferPointer, + to output: UnsafeMutableBufferPointer, + packetSize: Int32?) throws -> Int + { + var decodedCount: Int32 = 0 + if let size = packetSize { + decodedCount = opus_custom_decode_float( + decoder, + input.isEmpty ? nil : input.baseAddress, + size, + output.baseAddress!, + Int32(output.count) + ) + } else { + decodedCount = opus_decode_float( + decoder, + input.isEmpty ? nil : input.baseAddress, + Int32(input.count), + output.baseAddress!, + Int32(output.count), + 0 + ) + } if decodedCount < 0 { throw Opus.Error(decodedCount) } diff --git a/Sources/Opus/Opus.Encoder.swift b/Sources/Opus/Opus.Encoder.swift index 37dac29..107ed82 100644 --- a/Sources/Opus/Opus.Encoder.swift +++ b/Sources/Opus/Opus.Encoder.swift @@ -6,9 +6,10 @@ public extension Opus { let format: AVAudioFormat let application: Application let encoder: OpaquePointer + let customFrameSize: Int32? - // TODO: throw an error if format is unsupported public init(format: AVAudioFormat, application: Application = .audio) throws { + customFrameSize = nil if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument } @@ -24,11 +25,37 @@ public extension Opus { } } + public init(customOpus: OpaquePointer, + format: AVAudioFormat, + frameSize: UInt32, + application: Application = .audio) throws + { + customFrameSize = Int32(frameSize) + if !format.isValidOpusPCMFormat { + throw Opus.Error.badArgument + } + self.format = format + self.application = application + + // Initialize Opus encoder + var error: Opus.Error = .ok + encoder = opus_custom_encoder_create( + customOpus, + Int32(format.channelCount), + &error.rawValue + ) + if error != .ok { + throw error + } + } + deinit { opus_encoder_destroy(encoder) } public func reset() throws { + // A custom frame size means we're using opus custom + guard customFrameSize == nil else { return } let error = Opus.Error(opus_encoder_init(encoder, Int32(format.sampleRate), Int32(format.channelCount), application.rawValue)) if error != .ok { throw error @@ -47,28 +74,44 @@ public extension Opus.Encoder { return output.count } - func encode(_ input: AVAudioPCMBuffer, to output: inout [UInt8]) throws -> Int { + func encode(_ input: AVAudioPCMBuffer, compressedSize: Int) throws -> Data { + var compressed = Data(repeating: 0, count: compressedSize) + compressed.count = try compressed.withUnsafeMutableBytes( + { try encode(input, to: $0, compressedSize: compressedSize) } + ) + return compressed + } + + func encode(_ input: AVAudioPCMBuffer, to output: inout [UInt8], + compressedSize _: Int? = nil) throws -> Int + { try output.withUnsafeMutableBufferPointer { try encode(input, to: $0) } } - func encode(_ input: AVAudioPCMBuffer, to output: UnsafeMutableRawBufferPointer) throws -> Int { + func encode(_ input: AVAudioPCMBuffer, to output: UnsafeMutableRawBufferPointer, + compressedSize _: Int? = nil) throws -> Int + { let output = UnsafeMutableBufferPointer(start: output.baseAddress!.bindMemory(to: UInt8.self, capacity: output.count), count: output.count) return try encode(input, to: output) } - func encode(_ input: AVAudioPCMBuffer, to output: UnsafeMutableBufferPointer) throws -> Int { + func encode(_ input: AVAudioPCMBuffer, to output: UnsafeMutableBufferPointer, + compressedSize: Int? = nil) throws -> Int + { guard input.format.sampleRate == format.sampleRate, input.format.channelCount == format.channelCount else { throw Opus.Error.badArgument } switch format.commonFormat { case .pcmFormatInt16: - let input = UnsafeBufferPointer(start: input.int16ChannelData![0], count: Int(input.frameLength * format.channelCount)) - return try encode(input, to: output) + let input = UnsafeBufferPointer(start: input.int16ChannelData![0], + count: Int(input.frameLength * format.channelCount)) + return try encode(input, to: output, compressedSize: compressedSize) case .pcmFormatFloat32: - let input = UnsafeBufferPointer(start: input.floatChannelData![0], count: Int(input.frameLength * format.channelCount)) - return try encode(input, to: output) + let input = UnsafeBufferPointer(start: input.floatChannelData![0], + count: Int(input.frameLength * format.channelCount)) + return try encode(input, to: output, compressedSize: compressedSize) default: throw Opus.Error.badArgument } @@ -78,28 +121,58 @@ public extension Opus.Encoder { // MARK: private encode methods extension Opus.Encoder { - private func encode(_ input: UnsafeBufferPointer, to output: UnsafeMutableBufferPointer) throws -> Int { - let encodedSize = opus_encode( - encoder, - input.baseAddress!, - Int32(input.count) / Int32(format.channelCount), - output.baseAddress!, - Int32(output.count) - ) + private func encode(_ input: UnsafeBufferPointer, + to output: UnsafeMutableBufferPointer, + compressedSize: Int? = nil) throws -> Int + { + var encodedSize: Int32 = 0 + if let customSize = compressedSize, let frameSize = customFrameSize { + // Custom mode + encodedSize = opus_custom_encode( + encoder, + input.baseAddress!, + frameSize, + output.baseAddress!, + Int32(customSize) + ) + } else { + encodedSize = opus_encode( + encoder, + input.baseAddress!, + Int32(input.count) / Int32(format.channelCount), + output.baseAddress!, + Int32(output.count) + ) + } if encodedSize < 0 { throw Opus.Error(encodedSize) } return Int(encodedSize) } - private func encode(_ input: UnsafeBufferPointer, to output: UnsafeMutableBufferPointer) throws -> Int { - let encodedSize = opus_encode_float( - encoder, - input.baseAddress!, - Int32(input.count) / Int32(format.channelCount), - output.baseAddress!, - Int32(output.count) - ) + private func encode(_ input: UnsafeBufferPointer, + to output: UnsafeMutableBufferPointer, + compressedSize: Int? = nil) throws -> Int + { + var encodedSize: Int32 = 0 + if let customSize = compressedSize, let frameSize = customFrameSize { + // Custom mode + encodedSize = opus_custom_encode_float( + encoder, + input.baseAddress!, + frameSize, + output.baseAddress!, + Int32(customSize) + ) + } else { + encodedSize = opus_encode_float( + encoder, + input.baseAddress!, + Int32(input.count) / Int32(format.channelCount), + output.baseAddress!, + Int32(output.count) + ) + } if encodedSize < 0 { throw Opus.Error(encodedSize) } From 33c68f4e561c782b1606a02002ddacf88597b014 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Wed, 20 Apr 2022 12:59:35 -0700 Subject: [PATCH 33/37] Apply swiftformat --- Sources/Opus/Opus.Custom.swift | 5 +++-- Sources/Opus/Opus.Decoder.swift | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index 4798fb7..a7534cc 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -68,8 +68,9 @@ public extension Opus { /// - parameter compressedSize Opus packet size to compress to /// - Returns Data containing the Opus packet public func encode(_ avData: AVAudioPCMBuffer, - compressedSize: Int) throws -> Data { - return try encoder.encode(avData, compressedSize: compressedSize) + compressedSize: Int) throws -> Data + { + try encoder.encode(avData, compressedSize: compressedSize) } /// diff --git a/Sources/Opus/Opus.Decoder.swift b/Sources/Opus/Opus.Decoder.swift index 35376cf..d82016b 100644 --- a/Sources/Opus/Opus.Decoder.swift +++ b/Sources/Opus/Opus.Decoder.swift @@ -34,12 +34,12 @@ public extension Opus { self.format = format - // Initialize Opus decoder - var error: Opus.Error = .ok - decoder = opus_custom_decoder_create(customOpus, - Int32(format.channelCount), - &error.rawValue) - if error != .ok { + // Initialize Opus decoder + var error: Opus.Error = .ok + decoder = opus_custom_decoder_create(customOpus, + Int32(format.channelCount), + &error.rawValue) + if error != .ok { throw error } } From 033520fd45d63611ef8ed9eab0b006df48c274c3 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Thu, 21 Apr 2022 10:18:15 -0700 Subject: [PATCH 34/37] Rename to customFrameSize --- Sources/Opus/Opus.Custom.swift | 2 +- Sources/Opus/Opus.Decoder.swift | 4 ++-- Sources/Opus/Opus.Encoder.swift | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index a7534cc..dd95461 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -42,7 +42,7 @@ public extension Opus { // Create custom decoder decoder = try Opus.Decoder(customOpus: opusCustomMode, format: format, - frameSize: frameSize) + customFrameSize: frameSize) } deinit { diff --git a/Sources/Opus/Opus.Decoder.swift b/Sources/Opus/Opus.Decoder.swift index d82016b..13ae452 100644 --- a/Sources/Opus/Opus.Decoder.swift +++ b/Sources/Opus/Opus.Decoder.swift @@ -25,9 +25,9 @@ public extension Opus { public init(customOpus: OpaquePointer, format: AVAudioFormat, - frameSize: UInt32) throws + customFrameSize: UInt32) throws { - customFrameSize = Int32(frameSize) + self.customFrameSize = Int32(customFrameSize) if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument } diff --git a/Sources/Opus/Opus.Encoder.swift b/Sources/Opus/Opus.Encoder.swift index 107ed82..7d948c2 100644 --- a/Sources/Opus/Opus.Encoder.swift +++ b/Sources/Opus/Opus.Encoder.swift @@ -27,10 +27,10 @@ public extension Opus { public init(customOpus: OpaquePointer, format: AVAudioFormat, - frameSize: UInt32, + customFrameSize: UInt32, application: Application = .audio) throws { - customFrameSize = Int32(frameSize) + self.customFrameSize = Int32(customFrameSize) if !format.isValidOpusPCMFormat { throw Opus.Error.badArgument } From aa3db6f64d507cf6829adde6f2c3a416707f2f46 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Thu, 21 Apr 2022 11:12:16 -0700 Subject: [PATCH 35/37] One more rename --- Sources/Opus/Opus.Custom.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Opus/Opus.Custom.swift b/Sources/Opus/Opus.Custom.swift index dd95461..7e42aa2 100644 --- a/Sources/Opus/Opus.Custom.swift +++ b/Sources/Opus/Opus.Custom.swift @@ -38,7 +38,7 @@ public extension Opus { // Create custom encoder encoder = try Opus.Encoder(customOpus: opusCustomMode, format: format, - frameSize: frameSize) + customFrameSize: frameSize) // Create custom decoder decoder = try Opus.Decoder(customOpus: opusCustomMode, format: format, From 42d044f81a2b97eb8984def407288f29de4ee2d9 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton Date: Thu, 21 Apr 2022 12:18:54 -0700 Subject: [PATCH 36/37] Ensure that the compressed size is actually passed down --- Sources/Opus/Opus.Encoder.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/Opus/Opus.Encoder.swift b/Sources/Opus/Opus.Encoder.swift index 7d948c2..9aa95cf 100644 --- a/Sources/Opus/Opus.Encoder.swift +++ b/Sources/Opus/Opus.Encoder.swift @@ -83,18 +83,18 @@ public extension Opus.Encoder { } func encode(_ input: AVAudioPCMBuffer, to output: inout [UInt8], - compressedSize _: Int? = nil) throws -> Int + compressedSize: Int? = nil) throws -> Int { try output.withUnsafeMutableBufferPointer { - try encode(input, to: $0) + try encode(input, to: $0, compressedSize: compressedSize) } } func encode(_ input: AVAudioPCMBuffer, to output: UnsafeMutableRawBufferPointer, - compressedSize _: Int? = nil) throws -> Int + compressedSize: Int? = nil) throws -> Int { let output = UnsafeMutableBufferPointer(start: output.baseAddress!.bindMemory(to: UInt8.self, capacity: output.count), count: output.count) - return try encode(input, to: output) + return try encode(input, to: output, compressedSize: compressedSize) } func encode(_ input: AVAudioPCMBuffer, to output: UnsafeMutableBufferPointer, From f5f87354ea70c4eb657ee7d82af2cf145c440e95 Mon Sep 17 00:00:00 2001 From: Emlyn Bolton <3941071+emlynmac@users.noreply.github.com> Date: Tue, 3 Jan 2023 14:26:32 -0800 Subject: [PATCH 37/37] Always build optimized builds of Opus --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 688eda7..d08e1b6 100644 --- a/Package.swift +++ b/Package.swift @@ -90,7 +90,7 @@ let package = Package( .headerSearchPath("celt/x86"), .headerSearchPath("silk"), .headerSearchPath("silk/float"), - + .define("__OPTIMIZE__"), .define("OPUS_BUILD"), .define("CUSTOM_MODES"), .define("VAR_ARRAYS", to: "1"),