diff --git a/.dotnet/api/OpenAI.netstandard2.0.cs b/.dotnet/api/OpenAI.netstandard2.0.cs index 87abb883d..b21008e0c 100644 --- a/.dotnet/api/OpenAI.netstandard2.0.cs +++ b/.dotnet/api/OpenAI.netstandard2.0.cs @@ -1084,13 +1084,25 @@ public class AudioTranslationOptions : IJsonModel, IPer string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options); BinaryData IPersistableModel.Write(ModelReaderWriterOptions options); } - public enum GeneratedSpeechFormat { - Mp3 = 0, - Opus = 1, - Aac = 2, - Flac = 3, - Wav = 4, - Pcm = 5 + public readonly partial struct GeneratedSpeechFormat : IEquatable { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public GeneratedSpeechFormat(string value); + public static GeneratedSpeechFormat Aac { get; } + public static GeneratedSpeechFormat Flac { get; } + public static GeneratedSpeechFormat Mp3 { get; } + public static GeneratedSpeechFormat Opus { get; } + public static GeneratedSpeechFormat Pcm { get; } + public static GeneratedSpeechFormat Wav { get; } + public readonly bool Equals(GeneratedSpeechFormat other); + [EditorBrowsable(EditorBrowsableState.Never)] + public override readonly bool Equals(object obj); + [EditorBrowsable(EditorBrowsableState.Never)] + public override readonly int GetHashCode(); + public static bool operator ==(GeneratedSpeechFormat left, GeneratedSpeechFormat right); + public static implicit operator GeneratedSpeechFormat(string value); + public static bool operator !=(GeneratedSpeechFormat left, GeneratedSpeechFormat right); + public override readonly string ToString(); } public readonly partial struct GeneratedSpeechVoice : IEquatable { private readonly object _dummy; @@ -1120,7 +1132,7 @@ public static class OpenAIAudioModelFactory { } public class SpeechGenerationOptions : IJsonModel, IPersistableModel { public GeneratedSpeechFormat? ResponseFormat { get; set; } - public float? Speed { get; set; } + public float? SpeedRatio { get; set; } SpeechGenerationOptions IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options); void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options); SpeechGenerationOptions IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options); diff --git a/.dotnet/examples/CombinationExamples.cs b/.dotnet/examples/CombinationExamples.cs index 7987d81f2..ffa800c34 100644 --- a/.dotnet/examples/CombinationExamples.cs +++ b/.dotnet/examples/CombinationExamples.cs @@ -53,7 +53,7 @@ public void AlpacaArtAssessor() GeneratedSpeechVoice.Fable, new SpeechGenerationOptions() { - Speed = 0.9f, + SpeedRatio = 0.9f, ResponseFormat = GeneratedSpeechFormat.Opus, }); FileInfo ttsFileInfo = new($"{chatCompletion.Id}.opus"); @@ -89,7 +89,7 @@ public async Task CuriousCreatureCreator() GeneratedSpeechVoice.Onyx, new SpeechGenerationOptions() { - Speed = 1.1f, + SpeedRatio = 1.1f, ResponseFormat = GeneratedSpeechFormat.Opus, }); _ = Task.Run(async () => @@ -136,7 +136,7 @@ public async Task CuriousCreatureCreator() GeneratedSpeechVoice.Fable, new SpeechGenerationOptions() { - Speed = 0.9f, + SpeedRatio = 0.9f, ResponseFormat = GeneratedSpeechFormat.Opus, }); FileInfo criticAudioFileInfo = new($"{criticalAppraisalResult.Value.Id}-appraisal.opus"); diff --git a/.dotnet/src/Custom/Audio/GeneratedSpeechFormat.cs b/.dotnet/src/Custom/Audio/GeneratedSpeechFormat.cs index 4ee71fef4..8ef097051 100644 --- a/.dotnet/src/Custom/Audio/GeneratedSpeechFormat.cs +++ b/.dotnet/src/Custom/Audio/GeneratedSpeechFormat.cs @@ -1,32 +1,7 @@ namespace OpenAI.Audio; -/// -/// Represents an audio data format available as either input or output into an audio operation. -/// +/// The audio format in which to generate the speech. [CodeGenModel("CreateSpeechRequestResponseFormat")] -public enum GeneratedSpeechFormat +public readonly partial struct GeneratedSpeechFormat { - /// MP3. /// - [CodeGenMember("Mp3")] - Mp3, - - /// Opus. /// - [CodeGenMember("Opus")] - Opus, - - /// AAC (advanced audio coding). /// - [CodeGenMember("Aac")] - Aac, - - /// FLAC (free lossless audio codec). /// - [CodeGenMember("Flac")] - Flac, - - /// WAV. /// - [CodeGenMember("Wav")] - Wav, - - /// PCM (pulse-code modulation). /// - [CodeGenMember("Pcm")] - Pcm, } \ No newline at end of file diff --git a/.dotnet/src/Custom/Audio/SpeechGenerationOptions.cs b/.dotnet/src/Custom/Audio/SpeechGenerationOptions.cs index 7c67060fa..387d3c5b2 100644 --- a/.dotnet/src/Custom/Audio/SpeechGenerationOptions.cs +++ b/.dotnet/src/Custom/Audio/SpeechGenerationOptions.cs @@ -1,9 +1,6 @@ namespace OpenAI.Audio; -/// -/// A representation of additional options available to control the behavior of a text-to-speech audio generation -/// operation. -/// +/// The options to configure text-to-speech audio generation. [CodeGenModel("CreateSpeechRequest")] [CodeGenSuppress("SpeechGenerationOptions", typeof(InternalCreateSpeechRequestModel), typeof(string), typeof(GeneratedSpeechVoice))] public partial class SpeechGenerationOptions @@ -11,23 +8,20 @@ public partial class SpeechGenerationOptions // CUSTOM: // - Made internal. The model is specified by the client. // - Added setter. - /// One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd`. + [CodeGenMember("Model")] internal InternalCreateSpeechRequestModel Model { get; set; } // CUSTOM: // - Made internal. This value comes from a parameter on the client method. // - Added setter. /// The text to generate audio for. The maximum length is 4096 characters. + [CodeGenMember("Input")] internal string Input { get; set; } // CUSTOM: // - Made internal. This value comes from a parameter on the client method. // - Added setter. - /// - /// The voice to use when generating the audio. Supported voices are `alloy`, `echo`, `fable`, - /// `onyx`, `nova`, and `shimmer`. Previews of the voices are available in the - /// [Text to speech guide](/docs/guides/text-to-speech/voice-options). - /// + [CodeGenMember("Voice")] internal GeneratedSpeechVoice Voice { get; set; } // CUSTOM: Made public now that there are no required properties. @@ -35,4 +29,12 @@ public partial class SpeechGenerationOptions public SpeechGenerationOptions() { } + + // CUSTOM: Renamed. + /// + /// The speed of the generated audio expressed as a ratio between 0.5 and 2.0. The default is 1.0. + /// + [CodeGenMember("Speed")] + + public float? SpeedRatio { get; set; } } \ No newline at end of file diff --git a/.dotnet/src/Generated/Models/GeneratedSpeechFormat.Serialization.cs b/.dotnet/src/Generated/Models/GeneratedSpeechFormat.Serialization.cs deleted file mode 100644 index ff1d45f85..000000000 --- a/.dotnet/src/Generated/Models/GeneratedSpeechFormat.Serialization.cs +++ /dev/null @@ -1,33 +0,0 @@ -// - -#nullable disable - -using System; - -namespace OpenAI.Audio -{ - internal static partial class GeneratedSpeechFormatExtensions - { - public static string ToSerialString(this GeneratedSpeechFormat value) => value switch - { - GeneratedSpeechFormat.Mp3 => "mp3", - GeneratedSpeechFormat.Opus => "opus", - GeneratedSpeechFormat.Aac => "aac", - GeneratedSpeechFormat.Flac => "flac", - GeneratedSpeechFormat.Wav => "wav", - GeneratedSpeechFormat.Pcm => "pcm", - _ => throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown GeneratedSpeechFormat value.") - }; - - public static GeneratedSpeechFormat ToGeneratedSpeechFormat(this string value) - { - if (StringComparer.OrdinalIgnoreCase.Equals(value, "mp3")) return GeneratedSpeechFormat.Mp3; - if (StringComparer.OrdinalIgnoreCase.Equals(value, "opus")) return GeneratedSpeechFormat.Opus; - if (StringComparer.OrdinalIgnoreCase.Equals(value, "aac")) return GeneratedSpeechFormat.Aac; - if (StringComparer.OrdinalIgnoreCase.Equals(value, "flac")) return GeneratedSpeechFormat.Flac; - if (StringComparer.OrdinalIgnoreCase.Equals(value, "wav")) return GeneratedSpeechFormat.Wav; - if (StringComparer.OrdinalIgnoreCase.Equals(value, "pcm")) return GeneratedSpeechFormat.Pcm; - throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown GeneratedSpeechFormat value."); - } - } -} diff --git a/.dotnet/src/Generated/Models/GeneratedSpeechFormat.cs b/.dotnet/src/Generated/Models/GeneratedSpeechFormat.cs new file mode 100644 index 000000000..e8c256e31 --- /dev/null +++ b/.dotnet/src/Generated/Models/GeneratedSpeechFormat.cs @@ -0,0 +1,44 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Audio +{ + public readonly partial struct GeneratedSpeechFormat : IEquatable + { + private readonly string _value; + + public GeneratedSpeechFormat(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string Mp3Value = "mp3"; + private const string OpusValue = "opus"; + private const string AacValue = "aac"; + private const string FlacValue = "flac"; + private const string WavValue = "wav"; + private const string PcmValue = "pcm"; + + public static GeneratedSpeechFormat Mp3 { get; } = new GeneratedSpeechFormat(Mp3Value); + public static GeneratedSpeechFormat Opus { get; } = new GeneratedSpeechFormat(OpusValue); + public static GeneratedSpeechFormat Aac { get; } = new GeneratedSpeechFormat(AacValue); + public static GeneratedSpeechFormat Flac { get; } = new GeneratedSpeechFormat(FlacValue); + public static GeneratedSpeechFormat Wav { get; } = new GeneratedSpeechFormat(WavValue); + public static GeneratedSpeechFormat Pcm { get; } = new GeneratedSpeechFormat(PcmValue); + public static bool operator ==(GeneratedSpeechFormat left, GeneratedSpeechFormat right) => left.Equals(right); + public static bool operator !=(GeneratedSpeechFormat left, GeneratedSpeechFormat right) => !left.Equals(right); + public static implicit operator GeneratedSpeechFormat(string value) => new GeneratedSpeechFormat(value); + + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is GeneratedSpeechFormat other && Equals(other); + public bool Equals(GeneratedSpeechFormat other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value != null ? StringComparer.InvariantCultureIgnoreCase.GetHashCode(_value) : 0; + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/SpeechGenerationOptions.Serialization.cs b/.dotnet/src/Generated/Models/SpeechGenerationOptions.Serialization.cs index 9b2c260b6..823b6165b 100644 --- a/.dotnet/src/Generated/Models/SpeechGenerationOptions.Serialization.cs +++ b/.dotnet/src/Generated/Models/SpeechGenerationOptions.Serialization.cs @@ -39,12 +39,12 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade if (SerializedAdditionalRawData?.ContainsKey("response_format") != true && Optional.IsDefined(ResponseFormat)) { writer.WritePropertyName("response_format"u8); - writer.WriteStringValue(ResponseFormat.Value.ToSerialString()); + writer.WriteStringValue(ResponseFormat.Value.ToString()); } - if (SerializedAdditionalRawData?.ContainsKey("speed") != true && Optional.IsDefined(Speed)) + if (SerializedAdditionalRawData?.ContainsKey("speed") != true && Optional.IsDefined(SpeedRatio)) { writer.WritePropertyName("speed"u8); - writer.WriteNumberValue(Speed.Value); + writer.WriteNumberValue(SpeedRatio.Value); } if (SerializedAdditionalRawData != null) { @@ -118,7 +118,7 @@ internal static SpeechGenerationOptions DeserializeSpeechGenerationOptions(JsonE { continue; } - responseFormat = property.Value.GetString().ToGeneratedSpeechFormat(); + responseFormat = new GeneratedSpeechFormat(property.Value.GetString()); continue; } if (property.NameEquals("speed"u8)) diff --git a/.dotnet/src/Generated/Models/SpeechGenerationOptions.cs b/.dotnet/src/Generated/Models/SpeechGenerationOptions.cs index 4a5b48c18..8ecda5dc0 100644 --- a/.dotnet/src/Generated/Models/SpeechGenerationOptions.cs +++ b/.dotnet/src/Generated/Models/SpeechGenerationOptions.cs @@ -11,16 +11,15 @@ public partial class SpeechGenerationOptions { internal IDictionary SerializedAdditionalRawData { get; set; } - internal SpeechGenerationOptions(InternalCreateSpeechRequestModel model, string input, GeneratedSpeechVoice voice, GeneratedSpeechFormat? responseFormat, float? speed, IDictionary serializedAdditionalRawData) + internal SpeechGenerationOptions(InternalCreateSpeechRequestModel model, string input, GeneratedSpeechVoice voice, GeneratedSpeechFormat? responseFormat, float? speedRatio, IDictionary serializedAdditionalRawData) { Model = model; Input = input; Voice = voice; ResponseFormat = responseFormat; - Speed = speed; + SpeedRatio = speedRatio; SerializedAdditionalRawData = serializedAdditionalRawData; } public GeneratedSpeechFormat? ResponseFormat { get; set; } - public float? Speed { get; set; } } } diff --git a/.dotnet/tests/Audio/TextToSpeechTests.cs b/.dotnet/tests/Audio/TextToSpeechTests.cs index cbbd748d1..ca18fc32b 100644 --- a/.dotnet/tests/Audio/TextToSpeechTests.cs +++ b/.dotnet/tests/Audio/TextToSpeechTests.cs @@ -32,19 +32,29 @@ public async Task BasicTextToSpeechWorks() [Test] [TestCase(null)] - [TestCase(GeneratedSpeechFormat.Mp3)] - [TestCase(GeneratedSpeechFormat.Opus)] - [TestCase(GeneratedSpeechFormat.Aac)] - [TestCase(GeneratedSpeechFormat.Flac)] - [TestCase(GeneratedSpeechFormat.Wav)] - [TestCase(GeneratedSpeechFormat.Pcm)] - public async Task OutputFormatWorks(GeneratedSpeechFormat? responseFormat) + [TestCase("mp3")] + [TestCase("opus")] + [TestCase("aac")] + [TestCase("flac")] + [TestCase("wav")] + [TestCase("pcm")] + public async Task OutputFormatWorks(string responseFormat) { AudioClient client = GetTestClient(TestScenario.Audio_TTS); - SpeechGenerationOptions options = responseFormat == null - ? new() - : new() { ResponseFormat = responseFormat }; + SpeechGenerationOptions options = new() + { + ResponseFormat = responseFormat switch + { + "mp3" => GeneratedSpeechFormat.Mp3, + "opus" => GeneratedSpeechFormat.Opus, + "aac" => GeneratedSpeechFormat.Aac, + "flac" => GeneratedSpeechFormat.Flac, + "wav" => GeneratedSpeechFormat.Wav, + "pcm" => GeneratedSpeechFormat.Pcm, + _ => null + } + }; BinaryData audio = IsAsync ? await client.GenerateSpeechAsync("Hello, world!", GeneratedSpeechVoice.Alloy, options)