sysaudio: revive i24 samples
This commit is contained in:
parent
73a1ea4650
commit
cadaa3e85b
6 changed files with 262 additions and 291 deletions
|
|
@ -779,8 +779,7 @@ pub fn toAlsaFormat(format: main.Format) c.snd_pcm_format_t {
|
|||
return switch (format) {
|
||||
.u8 => c.SND_PCM_FORMAT_U8,
|
||||
.i16 => if (is_little) c.SND_PCM_FORMAT_S16_LE else c.SND_PCM_FORMAT_S16_BE,
|
||||
// TODO(i24)
|
||||
// .i24 => if (is_little) c.SND_PCM_FORMAT_S24_3LE else c.SND_PCM_FORMAT_S24_3BE,
|
||||
.i24 => if (is_little) c.SND_PCM_FORMAT_S24_3LE else c.SND_PCM_FORMAT_S24_3BE,
|
||||
.i32 => if (is_little) c.SND_PCM_FORMAT_S32_LE else c.SND_PCM_FORMAT_S32_BE,
|
||||
.f32 => if (is_little) c.SND_PCM_FORMAT_FLOAT_LE else c.SND_PCM_FORMAT_FLOAT_BE,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,19 +1,27 @@
|
|||
const std = @import("std");
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const asBytes = std.mem.asBytes;
|
||||
const bytesAsValue = std.mem.bytesAsValue;
|
||||
const shl = std.math.shl;
|
||||
const shr = std.math.shr;
|
||||
const maxInt = std.math.maxInt;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
|
||||
// TODO: SIMD
|
||||
pub fn unsignedToSigned(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
src_stride: u8,
|
||||
src: []const u8,
|
||||
comptime DstType: type,
|
||||
dst_stride: u8,
|
||||
dst: []u8,
|
||||
len: usize,
|
||||
) void {
|
||||
for (src, dst) |*src_sample, *dst_sample| {
|
||||
const half = (maxInt(SrcType) + 1) / 2;
|
||||
const trunc = @bitSizeOf(DestType) - @bitSizeOf(SrcType);
|
||||
dst_sample.* = shl(DestType, @intCast(src_sample.* -% half), trunc);
|
||||
const half = (maxInt(SrcType) + 1) / 2;
|
||||
const trunc = @bitSizeOf(DstType) - @bitSizeOf(SrcType);
|
||||
for (0..len) |i| {
|
||||
const src_sample: *const SrcType = @ptrCast(@alignCast(src[i * src_stride ..][0..src_stride]));
|
||||
const dst_sample: DstType = shl(DstType, @intCast(src_sample.* -% half), trunc);
|
||||
@memcpy(dst[i * dst_stride ..][0..dst_stride], asBytes(&dst_sample)[0..dst_stride]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -22,43 +30,55 @@ test unsignedToSigned {
|
|||
var u8_to_i24: [1]i24 = undefined;
|
||||
var u8_to_i32: [1]i32 = undefined;
|
||||
|
||||
unsignedToSigned(u8, &.{5}, i16, &u8_to_i16);
|
||||
unsignedToSigned(u8, &.{5}, i24, &u8_to_i24);
|
||||
unsignedToSigned(u8, &.{5}, i32, &u8_to_i32);
|
||||
unsignedToSigned(u8, 1, &[_]u8{5}, i16, 2, asBytes(&u8_to_i16), 1);
|
||||
unsignedToSigned(u8, 1, &[_]u8{5}, i24, 3, asBytes(&u8_to_i24), 1);
|
||||
unsignedToSigned(u8, 1, &[_]u8{5}, i32, 4, asBytes(&u8_to_i32), 1);
|
||||
|
||||
try expectEqual(@as(i16, -31488), u8_to_i16[0]);
|
||||
try expectEqual(@as(i24, -8060928), u8_to_i24[0]);
|
||||
try expectEqual(@as(i32, -2063597568), u8_to_i32[0]);
|
||||
}
|
||||
|
||||
// TODO: SIMD
|
||||
pub fn unsignedToFloat(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
src_stride: u8,
|
||||
src: []const u8,
|
||||
comptime DstType: type,
|
||||
dst_stride: u8,
|
||||
dst: []u8,
|
||||
len: usize,
|
||||
) void {
|
||||
for (src, dst) |*src_sample, *dst_sample| {
|
||||
const half = (maxInt(SrcType) + 1) / 2;
|
||||
dst_sample.* = (@as(DestType, @floatFromInt(src_sample.*)) - half) * 1.0 / half;
|
||||
const half = (maxInt(SrcType) + 1) / 2;
|
||||
for (0..len) |i| {
|
||||
const src_sample: *const SrcType = @ptrCast(@alignCast(src[i * src_stride ..][0..src_stride]));
|
||||
const dst_sample: DstType = (@as(DstType, @floatFromInt(src_sample.*)) - half) * 1.0 / half;
|
||||
@memcpy(dst[i * dst_stride ..][0..dst_stride], asBytes(&dst_sample)[0..dst_stride]);
|
||||
}
|
||||
}
|
||||
|
||||
test unsignedToFloat {
|
||||
var u8_to_f32: [1]f32 = undefined;
|
||||
unsignedToFloat(u8, &.{5}, f32, &u8_to_f32);
|
||||
unsignedToFloat(u8, 1, &[_]u8{5}, f32, 4, asBytes(&u8_to_f32), 1);
|
||||
try expectEqual(@as(f32, -0.9609375), u8_to_f32[0]);
|
||||
}
|
||||
|
||||
// TODO: SIMD
|
||||
pub fn signedToUnsigned(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
src_stride: u8,
|
||||
src: []const u8,
|
||||
comptime DstType: type,
|
||||
dst_stride: u8,
|
||||
dst: []u8,
|
||||
len: usize,
|
||||
) void {
|
||||
for (src, dst) |*src_sample, *dst_sample| {
|
||||
const half = (maxInt(DestType) + 1) / 2;
|
||||
const trunc = @bitSizeOf(SrcType) - @bitSizeOf(DestType);
|
||||
dst_sample.* = shr(DestType, @intCast(src_sample.*), trunc) + half;
|
||||
const half = (maxInt(DstType) + 1) / 2;
|
||||
const trunc = @bitSizeOf(SrcType) - @bitSizeOf(DstType);
|
||||
for (0..len) |i| {
|
||||
const src_sample: *const SrcType = @ptrCast(@alignCast(src[i * src_stride ..][0..src_stride]));
|
||||
const dst_sample: DstType = shr(DstType, @intCast(src_sample.*), trunc) + half;
|
||||
@memcpy(dst[i * dst_stride ..][0..dst_stride], asBytes(&dst_sample)[0..dst_stride]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,9 +87,9 @@ test signedToUnsigned {
|
|||
var i24_to_u8: [1]u8 = undefined;
|
||||
var i32_to_u8: [1]u8 = undefined;
|
||||
|
||||
signedToUnsigned(i16, &.{5}, u8, &i16_to_u8);
|
||||
signedToUnsigned(i24, &.{5}, u8, &i24_to_u8);
|
||||
signedToUnsigned(i32, &.{5}, u8, &i32_to_u8);
|
||||
signedToUnsigned(i16, 2, asBytes(&[_]i16{5}), u8, 1, asBytes(&i16_to_u8), 1);
|
||||
signedToUnsigned(i24, 3, asBytes(&[_]i24{5}), u8, 1, asBytes(&i24_to_u8), 1);
|
||||
signedToUnsigned(i32, 4, asBytes(&[_]i32{5}), u8, 1, asBytes(&i32_to_u8), 1);
|
||||
|
||||
try expectEqual(@as(u8, 128), i16_to_u8[0]);
|
||||
try expectEqual(@as(u8, 128), i24_to_u8[0]);
|
||||
|
|
@ -78,31 +98,38 @@ test signedToUnsigned {
|
|||
|
||||
pub fn signedToSigned(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
src_stride: u8,
|
||||
src: []const u8,
|
||||
comptime DstType: type,
|
||||
dst_stride: u8,
|
||||
dst: []u8,
|
||||
len: usize,
|
||||
) void {
|
||||
// TODO: Uncomment this (zig crashes)
|
||||
// if (std.simd.suggestVectorLength(SrcType)) |_| {
|
||||
// signedToSignedSIMD(SrcType, src, DestType, dst);
|
||||
// } else {
|
||||
signedToSignedScalar(SrcType, src, DestType, dst);
|
||||
// }
|
||||
}
|
||||
const trunc = @bitSizeOf(SrcType) - @bitSizeOf(DstType);
|
||||
var i: usize = 0;
|
||||
|
||||
pub fn signedToSignedScalar(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
) void {
|
||||
for (src, dst) |*src_sample, *dst_sample| {
|
||||
const trunc = @bitSizeOf(SrcType) - @bitSizeOf(DestType);
|
||||
dst_sample.* = shr(DestType, @intCast(src_sample.*), trunc);
|
||||
// Use SIMD when available
|
||||
if (std.simd.suggestVectorLength(SrcType)) |vec_size| {
|
||||
const VecSrc = @Vector(vec_size, SrcType);
|
||||
const VecDst = @Vector(vec_size, DstType);
|
||||
const vec_blocks_len = len - (len % vec_size);
|
||||
while (i < vec_blocks_len) : (i += vec_size) {
|
||||
const src_vec = bytesAsValue(VecSrc, src[i * src_stride ..][0 .. vec_size * src_stride]).*;
|
||||
const dst_sample: VecDst = shr(VecDst, @intCast(src_vec), trunc);
|
||||
@memcpy(dst[i * dst_stride ..][0 .. vec_size * dst_stride], asBytes(&dst_sample)[0 .. vec_size * dst_stride]);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the remaining samples
|
||||
|
||||
while (i < len) : (i += 1) {
|
||||
const src_sample: *const SrcType = @ptrCast(@alignCast(src[i * src_stride ..][0..src_stride]));
|
||||
const dst_sample: DstType = shr(DstType, @intCast(src_sample.*), trunc);
|
||||
@memcpy(dst[i * dst_stride ..][0..dst_stride], asBytes(&dst_sample)[0..dst_stride]);
|
||||
}
|
||||
}
|
||||
|
||||
test signedToSignedScalar {
|
||||
test "signedToSigned single" {
|
||||
var i16_to_i24: [1]i24 = undefined;
|
||||
var i16_to_i32: [1]i32 = undefined;
|
||||
var i24_to_i16: [1]i16 = undefined;
|
||||
|
|
@ -110,14 +137,14 @@ test signedToSignedScalar {
|
|||
var i32_to_i16: [1]i16 = undefined;
|
||||
var i32_to_i24: [1]i24 = undefined;
|
||||
|
||||
signedToSignedScalar(i24, &.{5}, i16, &i24_to_i16);
|
||||
signedToSignedScalar(i32, &.{5}, i16, &i32_to_i16);
|
||||
signedToSigned(i24, 3, asBytes(&[_]i24{5}), i16, 2, asBytes(&i24_to_i16), 1);
|
||||
signedToSigned(i32, 4, asBytes(&[_]i32{5}), i16, 2, asBytes(&i32_to_i16), 1);
|
||||
|
||||
signedToSignedScalar(i16, &.{5}, i24, &i16_to_i24);
|
||||
signedToSignedScalar(i32, &.{5}, i24, &i32_to_i24);
|
||||
signedToSigned(i16, 2, asBytes(&[_]i16{5}), i24, 3, asBytes(&i16_to_i24), 1);
|
||||
signedToSigned(i32, 4, asBytes(&[_]i32{5}), i24, 3, asBytes(&i32_to_i24), 1);
|
||||
|
||||
signedToSignedScalar(i16, &.{5}, i32, &i16_to_i32);
|
||||
signedToSignedScalar(i24, &.{5}, i32, &i24_to_i32);
|
||||
signedToSigned(i16, 2, asBytes(&[_]i16{5}), i32, 4, asBytes(&i16_to_i32), 1);
|
||||
signedToSigned(i24, 3, asBytes(&[_]i24{5}), i32, 4, asBytes(&i24_to_i32), 1);
|
||||
|
||||
try expectEqual(@as(i24, 1280), i16_to_i24[0]);
|
||||
try expectEqual(@as(i32, 327680), i16_to_i32[0]);
|
||||
|
|
@ -129,221 +156,173 @@ test signedToSignedScalar {
|
|||
try expectEqual(@as(i24, 0), i32_to_i24[0]);
|
||||
}
|
||||
|
||||
pub fn signedToSignedSIMD(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
) void {
|
||||
const vec_size = std.simd.suggestVectorLength(SrcType).?;
|
||||
const VecSrc = @Vector(vec_size, SrcType);
|
||||
const VecDst = @Vector(vec_size, DestType);
|
||||
const trunc = @bitSizeOf(SrcType) - @bitSizeOf(DestType);
|
||||
const vec_blocks_len = src.len - (src.len % vec_size);
|
||||
var i: usize = 0;
|
||||
while (i < vec_blocks_len) : (i += vec_size) {
|
||||
const src_vec: VecSrc = src[i..][0..vec_size].*;
|
||||
dst[i..][0..vec_size].* = shr(VecDst, @intCast(src_vec), trunc);
|
||||
}
|
||||
if (i != src.len) signedToSignedScalar(SrcType, src[i..], DestType, dst[i..]);
|
||||
}
|
||||
|
||||
test signedToSignedSIMD {
|
||||
var i16_to_i32: [32 + 7]i32 = undefined;
|
||||
const items = [1]i16{5} ** (32 + 7);
|
||||
signedToSignedSIMD(i16, &items, i32, &i16_to_i32);
|
||||
test "signedToSigned multi" {
|
||||
const len = 32 + 7;
|
||||
var i16_to_i32: [len]i32 = undefined;
|
||||
const items = [1]i16{5} ** (len);
|
||||
signedToSigned(i16, 2, asBytes(&items), i32, 4, asBytes(&i16_to_i32), len);
|
||||
try expectEqual(@as(i32, 327680), i16_to_i32[0]);
|
||||
try expectEqual(i16_to_i32[0], i16_to_i32[i16_to_i32.len - 1]);
|
||||
}
|
||||
|
||||
pub fn signedToFloat(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
src_stride: u8,
|
||||
src: []const u8,
|
||||
comptime DstType: type,
|
||||
dst_stride: u8,
|
||||
dst: []u8,
|
||||
len: usize,
|
||||
) void {
|
||||
if (std.simd.suggestVectorLength(SrcType)) |_| {
|
||||
signedToFloatSIMD(SrcType, src, DestType, dst);
|
||||
} else {
|
||||
signedToFloatScalar(SrcType, src, DestType, dst);
|
||||
const div_by_max = 1.0 / @as(comptime_float, maxInt(SrcType) + 1);
|
||||
var i: usize = 0;
|
||||
|
||||
// Use SIMD when available
|
||||
if (std.simd.suggestVectorLength(SrcType)) |vec_size| {
|
||||
const VecSrc = @Vector(vec_size, SrcType);
|
||||
const VecDst = @Vector(vec_size, DstType);
|
||||
const vec_blocks_len = len - (len % vec_size);
|
||||
const div_by_max_vec: VecDst = @splat(div_by_max);
|
||||
while (i < vec_blocks_len) : (i += vec_size) {
|
||||
const src_vec = bytesAsValue(VecSrc, src[i * src_stride ..][0 .. vec_size * src_stride]).*;
|
||||
const dst_sample: VecDst = @as(VecDst, @floatFromInt(src_vec)) * div_by_max_vec;
|
||||
@memcpy(dst[i * dst_stride ..][0 .. vec_size * dst_stride], asBytes(&dst_sample)[0 .. vec_size * dst_stride]);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the remaining samples
|
||||
while (i < len) : (i += 1) {
|
||||
const src_sample: *const SrcType = @ptrCast(@alignCast(src[i * src_stride ..][0..src_stride]));
|
||||
const dst_sample: DstType = @as(DstType, @floatFromInt(src_sample.*)) * div_by_max;
|
||||
@memcpy(dst[i * dst_stride ..][0..dst_stride], asBytes(&dst_sample)[0..dst_stride]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn signedToFloatScalar(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
) void {
|
||||
const max: comptime_float = maxInt(SrcType) + 1;
|
||||
const div_by_max = 1.0 / max;
|
||||
for (src, dst) |*src_sample, *dst_sample| {
|
||||
dst_sample.* = @as(DestType, @floatFromInt(src_sample.*)) * div_by_max;
|
||||
}
|
||||
}
|
||||
|
||||
test signedToFloatScalar {
|
||||
test "signedToFloat single" {
|
||||
var i16_to_f32: [1]f32 = undefined;
|
||||
var i24_to_f32: [1]f32 = undefined;
|
||||
var i32_to_f32: [1]f32 = undefined;
|
||||
|
||||
signedToFloatScalar(i16, &.{5}, f32, &i16_to_f32);
|
||||
signedToFloatScalar(i24, &.{5}, f32, &i24_to_f32);
|
||||
signedToFloatScalar(i32, &.{5}, f32, &i32_to_f32);
|
||||
signedToFloat(i16, 2, asBytes(&[_]i16{5}), f32, 4, asBytes(&i16_to_f32), 1);
|
||||
signedToFloat(i24, 3, asBytes(&[_]i24{5}), f32, 4, asBytes(&i24_to_f32), 1);
|
||||
signedToFloat(i32, 4, asBytes(&[_]i32{5}), f32, 4, asBytes(&i32_to_f32), 1);
|
||||
|
||||
try expectEqual(@as(f32, 1.52587890625e-4), i16_to_f32[0]);
|
||||
try expectEqual(@as(f32, 5.9604644775391e-7), i24_to_f32[0]);
|
||||
try expectEqual(@as(f32, 2.32830643e-09), i32_to_f32[0]);
|
||||
}
|
||||
|
||||
pub fn signedToFloatSIMD(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
) void {
|
||||
const vec_size = std.simd.suggestVectorLength(SrcType).?;
|
||||
const VecSrc = @Vector(vec_size, SrcType);
|
||||
const VecDst = @Vector(vec_size, DestType);
|
||||
const div_by_max: VecDst = @splat(1.0 / @as(comptime_float, maxInt(SrcType) + 1));
|
||||
const vec_blocks_len = src.len - (src.len % vec_size);
|
||||
var i: usize = 0;
|
||||
while (i < vec_blocks_len) : (i += vec_size) {
|
||||
const src_vec: VecSrc = src[i..][0..vec_size].*;
|
||||
dst[i..][0..vec_size].* = @as(VecDst, @floatFromInt(src_vec)) * div_by_max;
|
||||
}
|
||||
if (i != src.len) signedToFloatScalar(SrcType, src[i..], DestType, dst[i..]);
|
||||
}
|
||||
|
||||
test signedToFloatSIMD {
|
||||
var i32_to_f32: [32 + 7]f32 = undefined;
|
||||
const items = [1]i32{5} ** (32 + 7);
|
||||
signedToFloatSIMD(i32, &items, f32, &i32_to_f32);
|
||||
test "signedToFloat multi" {
|
||||
const len = 32 + 7;
|
||||
var i32_to_f32: [len]f32 = undefined;
|
||||
const items = [1]i32{5} ** (len);
|
||||
signedToFloat(i32, 4, asBytes(&items), f32, 4, asBytes(&i32_to_f32), len);
|
||||
try expectEqual(@as(f32, 2.32830643e-09), i32_to_f32[0]);
|
||||
try expectEqual(i32_to_f32[0], i32_to_f32[i32_to_f32.len - 1]);
|
||||
}
|
||||
|
||||
pub fn floatToUnsigned(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
src_stride: u8,
|
||||
src: []const u8,
|
||||
comptime DstType: type,
|
||||
dst_stride: u8,
|
||||
dst: []u8,
|
||||
len: usize,
|
||||
) void {
|
||||
if (std.simd.suggestVectorLength(SrcType)) |_| {
|
||||
floatToUnsignedSIMD(SrcType, src, DestType, dst);
|
||||
} else {
|
||||
floatToUnsignedScalar(SrcType, src, DestType, dst);
|
||||
const half = maxInt(DstType) / 2;
|
||||
const half_plus_one = half + 1;
|
||||
var i: usize = 0;
|
||||
|
||||
// Use SIMD when available
|
||||
if (std.simd.suggestVectorLength(SrcType)) |vec_size| {
|
||||
const VecSrc = @Vector(vec_size, SrcType);
|
||||
const VecDst = @Vector(vec_size, DstType);
|
||||
const half_vec: VecSrc = @splat(half);
|
||||
const half_plus_one_vec: VecSrc = @splat(half_plus_one);
|
||||
const vec_blocks_len = len - (len % vec_size);
|
||||
while (i < vec_blocks_len) : (i += vec_size) {
|
||||
const src_vec = bytesAsValue(VecSrc, src[i * src_stride ..][0 .. vec_size * src_stride]).*;
|
||||
const dst_sample: VecDst = @intFromFloat(src_vec * half_vec + half_plus_one_vec);
|
||||
@memcpy(dst[i * dst_stride ..][0 .. vec_size * dst_stride], asBytes(&dst_sample)[0 .. vec_size * dst_stride]);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the remaining samples
|
||||
while (i < len) : (i += 1) {
|
||||
const src_sample: *const SrcType = @ptrCast(@alignCast(src[i * src_stride ..][0..src_stride]));
|
||||
const dst_sample: DstType = @intFromFloat(src_sample.* * half + half_plus_one);
|
||||
@memcpy(dst[i * dst_stride ..][0..dst_stride], asBytes(&dst_sample)[0..dst_stride]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn floatToUnsignedScalar(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
) void {
|
||||
for (src, dst) |*src_sample, *dst_sample| {
|
||||
const half = maxInt(DestType) / 2;
|
||||
dst_sample.* = @intFromFloat(src_sample.* * half + (half + 1));
|
||||
}
|
||||
}
|
||||
|
||||
test floatToUnsignedScalar {
|
||||
test "floatToUnsigned single" {
|
||||
var f32_to_u8: [1]u8 = undefined;
|
||||
floatToUnsignedScalar(f32, &.{0.5}, u8, &f32_to_u8);
|
||||
floatToUnsigned(f32, 4, asBytes(&[_]f32{0.5}), u8, 1, asBytes(&f32_to_u8), 1);
|
||||
try expectEqual(@as(u8, 191), f32_to_u8[0]);
|
||||
}
|
||||
|
||||
pub fn floatToUnsignedSIMD(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
) void {
|
||||
const vec_size = std.simd.suggestVectorLength(SrcType).?;
|
||||
const VecSrc = @Vector(vec_size, SrcType);
|
||||
const VecDst = @Vector(vec_size, DestType);
|
||||
const half: VecSrc = @splat(maxInt(DestType) / 2);
|
||||
const half_plus_one: VecSrc = @splat(maxInt(DestType) / 2 + 1);
|
||||
const vec_blocks_len = src.len - (src.len % vec_size);
|
||||
var i: usize = 0;
|
||||
while (i < vec_blocks_len) : (i += vec_size) {
|
||||
const src_vec: VecSrc = src[i..][0..vec_size].*;
|
||||
dst[i..][0..vec_size].* = @as(VecDst, @intFromFloat(src_vec * half + half_plus_one));
|
||||
}
|
||||
if (i != src.len) floatToUnsignedScalar(SrcType, src[i..], DestType, dst[i..]);
|
||||
}
|
||||
|
||||
test floatToUnsignedSIMD {
|
||||
var f32_to_u8: [32 + 7]u8 = undefined;
|
||||
const items = [1]f32{0.5} ** (32 + 7);
|
||||
floatToUnsignedSIMD(f32, &items, u8, &f32_to_u8);
|
||||
test "floatToUnsigned multi" {
|
||||
const len = 32 + 7;
|
||||
var f32_to_u8: [len]u8 = undefined;
|
||||
const items = [1]f32{0.5} ** (len);
|
||||
floatToUnsigned(f32, 4, asBytes(&items), u8, 1, asBytes(&f32_to_u8), len);
|
||||
try expectEqual(@as(u8, 191), f32_to_u8[0]);
|
||||
try expectEqual(f32_to_u8[0], f32_to_u8[f32_to_u8.len - 1]);
|
||||
}
|
||||
|
||||
pub fn floatToSigned(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
src_stride: u8,
|
||||
src: []const u8,
|
||||
comptime DstType: type,
|
||||
dst_stride: u8,
|
||||
dst: []u8,
|
||||
len: usize,
|
||||
) void {
|
||||
if (std.simd.suggestVectorLength(SrcType)) |_| {
|
||||
floatToSignedSIMD(SrcType, src, DestType, dst);
|
||||
} else {
|
||||
floatToSignedScalar(SrcType, src, DestType, dst);
|
||||
const max = maxInt(DstType) + 1;
|
||||
var i: usize = 0;
|
||||
|
||||
// Use SIMD when available
|
||||
if (std.simd.suggestVectorLength(SrcType)) |vec_size| {
|
||||
const VecSrc = @Vector(vec_size, SrcType);
|
||||
const VecDst = @Vector(vec_size, DstType);
|
||||
const max_vec: VecSrc = @splat(max);
|
||||
const vec_blocks_len = len - (len % vec_size);
|
||||
while (i < vec_blocks_len) : (i += vec_size) {
|
||||
const src_vec = bytesAsValue(VecSrc, src[i * src_stride ..][0 .. vec_size * src_stride]).*;
|
||||
const dst_sample: VecDst = @intFromFloat(src_vec * max_vec);
|
||||
@memcpy(dst[i * dst_stride ..][0 .. vec_size * dst_stride], asBytes(&dst_sample)[0 .. vec_size * dst_stride]);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the remaining samples
|
||||
while (i < len) : (i += 1) {
|
||||
const src_sample: *const SrcType = @ptrCast(@alignCast(src[i * src_stride ..][0..src_stride]));
|
||||
const dst_sample: DstType = @truncate(@as(i32, @intFromFloat(src_sample.* * max)));
|
||||
@memcpy(dst[i * dst_stride ..][0..dst_stride], asBytes(&dst_sample)[0..dst_stride]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn floatToSignedScalar(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
) void {
|
||||
for (src, dst) |*src_sample, *dst_sample| {
|
||||
const max = maxInt(DestType) + 1;
|
||||
dst_sample.* = @truncate(@as(i32, @intFromFloat(src_sample.* * max)));
|
||||
}
|
||||
}
|
||||
|
||||
test floatToSignedScalar {
|
||||
test "floatToSigned single" {
|
||||
var f32_to_i16: [1]i16 = undefined;
|
||||
var f32_to_i24: [1]i24 = undefined;
|
||||
var f32_to_i32: [1]i32 = undefined;
|
||||
|
||||
floatToSignedScalar(f32, &.{0.5}, i16, &f32_to_i16);
|
||||
floatToSignedScalar(f32, &.{0.5}, i24, &f32_to_i24);
|
||||
floatToSignedScalar(f32, &.{0.5}, i32, &f32_to_i32);
|
||||
floatToSigned(f32, 4, asBytes(&[_]f32{0.5}), i16, 2, asBytes(&f32_to_i16), 1);
|
||||
floatToSigned(f32, 4, asBytes(&[_]f32{0.5}), i24, 3, asBytes(&f32_to_i24), 1);
|
||||
floatToSigned(f32, 4, asBytes(&[_]f32{0.5}), i32, 4, asBytes(&f32_to_i32), 1);
|
||||
|
||||
try expectEqual(@as(i16, 16384), f32_to_i16[0]);
|
||||
try expectEqual(@as(i24, 4194304), f32_to_i24[0]);
|
||||
try expectEqual(@as(i32, 1073741824), f32_to_i32[0]);
|
||||
}
|
||||
|
||||
pub fn floatToSignedSIMD(
|
||||
comptime SrcType: type,
|
||||
src: []const SrcType,
|
||||
comptime DestType: type,
|
||||
dst: []DestType,
|
||||
) void {
|
||||
const vec_size = std.simd.suggestVectorLength(SrcType).?;
|
||||
const VecSrc = @Vector(vec_size, SrcType);
|
||||
const VecDst = @Vector(vec_size, DestType);
|
||||
const max: VecSrc = @splat(maxInt(DestType) + 1);
|
||||
const vec_blocks_len = src.len - (src.len % vec_size);
|
||||
var i: usize = 0;
|
||||
while (i < vec_blocks_len) : (i += vec_size) {
|
||||
const src_vec: VecSrc = src[i..][0..vec_size].*;
|
||||
dst[i..][0..vec_size].* = @as(VecDst, @intFromFloat(src_vec * max));
|
||||
}
|
||||
if (i != src.len) floatToSignedScalar(SrcType, src[i..], DestType, dst[i..]);
|
||||
}
|
||||
|
||||
test floatToSignedSIMD {
|
||||
var f32_to_i16: [32 + 7]i16 = undefined;
|
||||
const items = [1]f32{0.5} ** (32 + 7);
|
||||
floatToSignedSIMD(f32, &items, i16, &f32_to_i16);
|
||||
test "floatToSigned multi" {
|
||||
const len = 32 + 7;
|
||||
var f32_to_i16: [len]i16 = undefined;
|
||||
const items = [1]f32{0.5} ** (len);
|
||||
floatToSigned(f32, 4, asBytes(&items), i16, 2, asBytes(&f32_to_i16), len);
|
||||
try expectEqual(@as(i16, 16384), f32_to_i16[0]);
|
||||
try expectEqual(f32_to_i16[0], f32_to_i16[f32_to_i16.len - 1]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -742,8 +742,7 @@ fn createStreamDesc(format: main.Format, sample_rate: u24, ch_count: usize) !c.A
|
|||
.mFormatID = c.kAudioFormatLinearPCM,
|
||||
.mFormatFlags = switch (format) {
|
||||
.i16 => c.kAudioFormatFlagIsSignedInteger,
|
||||
// TODO(i24)
|
||||
// .i24 => c.kAudioFormatFlagIsSignedInteger,
|
||||
.i24 => c.kAudioFormatFlagIsSignedInteger,
|
||||
.i32 => c.kAudioFormatFlagIsSignedInteger,
|
||||
.f32 => c.kAudioFormatFlagIsFloat,
|
||||
.u8 => return error.IncompatibleDevice,
|
||||
|
|
@ -754,8 +753,7 @@ fn createStreamDesc(format: main.Format, sample_rate: u24, ch_count: usize) !c.A
|
|||
.mChannelsPerFrame = @intCast(ch_count),
|
||||
.mBitsPerChannel = switch (format) {
|
||||
.i16 => 16,
|
||||
// TODO(i24)
|
||||
// .i24 => 24,
|
||||
.i24 => 24,
|
||||
.i32 => 32,
|
||||
.f32 => 32,
|
||||
.u8 => return error.IncompatibleDevice,
|
||||
|
|
|
|||
|
|
@ -321,85 +321,89 @@ pub const Recorder = struct {
|
|||
}
|
||||
};
|
||||
|
||||
pub fn convertTo(comptime SrcType: type, src: []const SrcType, dst_format: Format, dst: []u8) void {
|
||||
const dst_len = dst.len / dst_format.size();
|
||||
std.debug.assert(dst_len == src.len);
|
||||
pub fn convertTo(comptime SrcType: type, src: []const SrcType, dst_format: Format, dst_bytes: []u8) void {
|
||||
const src_stride = @bitSizeOf(SrcType) / 8;
|
||||
const dst_stride = dst_format.size();
|
||||
const src_bytes = @as([*]const u8, @ptrCast(@alignCast(src)))[0 .. src.len * src_stride];
|
||||
std.debug.assert(@bitSizeOf(SrcType) % 8 == 0);
|
||||
std.debug.assert(dst_bytes.len / dst_stride == src.len);
|
||||
|
||||
return switch (dst_format) {
|
||||
.u8 => switch (SrcType) {
|
||||
u8 => @memcpy(@as([*]u8, @ptrCast(@alignCast(dst)))[0..dst_len], src),
|
||||
i8, i16, i24, i32 => conv.signedToUnsigned(SrcType, src, u8, @as([*]u8, @ptrCast(@alignCast(dst)))[0..dst_len]),
|
||||
f32 => conv.floatToUnsigned(SrcType, src, u8, @as([*]u8, @ptrCast(@alignCast(dst)))[0..dst_len]),
|
||||
u8 => @memcpy(dst_bytes, src_bytes),
|
||||
i8, i16, i24, i32 => conv.signedToUnsigned(SrcType, src_stride, src_bytes, u8, dst_stride, dst_bytes, src.len),
|
||||
f32 => conv.floatToUnsigned(SrcType, src_stride, src_bytes, u8, dst_stride, dst_bytes, src.len),
|
||||
else => unreachable,
|
||||
},
|
||||
.i16 => switch (SrcType) {
|
||||
i16 => @memcpy(@as([*]i16, @ptrCast(@alignCast(dst)))[0..dst_len], src),
|
||||
u8 => conv.unsignedToSigned(SrcType, src, i16, @as([*]i16, @ptrCast(@alignCast(dst)))[0..dst_len]),
|
||||
i8, i24, i32 => conv.signedToSigned(SrcType, src, i16, @as([*]i16, @ptrCast(@alignCast(dst)))[0..dst_len]),
|
||||
f32 => conv.floatToSigned(SrcType, src, i16, @as([*]i16, @ptrCast(@alignCast(dst)))[0..dst_len]),
|
||||
i16 => @memcpy(dst_bytes, src_bytes),
|
||||
u8 => conv.unsignedToSigned(SrcType, src_stride, src_bytes, i16, dst_stride, dst_bytes, src.len),
|
||||
i8, i24, i32 => conv.signedToSigned(SrcType, src_stride, src_bytes, i16, dst_stride, dst_bytes, src.len),
|
||||
f32 => conv.floatToSigned(SrcType, src_stride, src_bytes, i16, dst_stride, dst_bytes, src.len),
|
||||
else => unreachable,
|
||||
},
|
||||
.i24 => switch (SrcType) {
|
||||
i24 => @memcpy(dst_bytes, src_bytes),
|
||||
u8 => conv.unsignedToSigned(SrcType, src_stride, src_bytes, i24, dst_stride, dst_bytes, src.len),
|
||||
i8, i16, i32 => conv.signedToSigned(SrcType, src_stride, src_bytes, i24, dst_stride, dst_bytes, src.len),
|
||||
f32 => conv.floatToSigned(SrcType, src_stride, src_bytes, i24, dst_stride, dst_bytes, src.len),
|
||||
else => unreachable,
|
||||
},
|
||||
// TODO(i24)
|
||||
// .i24 => switch (SrcType) {
|
||||
// i24 => @memcpy(@as([*]i24, @ptrCast(@alignCast(dst)))[0..dst_len], src),
|
||||
// u8 => conv.unsignedToSigned(SrcType, src, i24, @as([*]i24, @ptrCast(@alignCast(dst)))[0..dst_len]),
|
||||
// i8, i16, i32 => conv.signedToSigned(SrcType, src, i24, @as([*]i24, @ptrCast(@alignCast(dst)))[0..dst_len]),
|
||||
// f32 => conv.floatToSigned(SrcType, src, i24, @as([*]i24, @ptrCast(@alignCast(dst)))[0..dst_len]),
|
||||
// else => unreachable,
|
||||
// },
|
||||
.i32 => switch (SrcType) {
|
||||
i32 => @memcpy(@as([*]i32, @ptrCast(@alignCast(dst)))[0..dst_len], src),
|
||||
u8 => conv.unsignedToSigned(SrcType, src, i32, @as([*]i32, @ptrCast(@alignCast(dst)))[0..dst_len]),
|
||||
i8, i16, i24 => conv.signedToSigned(SrcType, src, i32, @as([*]i32, @ptrCast(@alignCast(dst)))[0..dst_len]),
|
||||
f32 => conv.floatToSigned(SrcType, src, i32, @as([*]i32, @ptrCast(@alignCast(dst)))[0..dst_len]),
|
||||
i32 => @memcpy(dst_bytes, src_bytes),
|
||||
u8 => conv.unsignedToSigned(SrcType, src_stride, src_bytes, i32, dst_stride, dst_bytes, src.len),
|
||||
i8, i16, i24 => conv.signedToSigned(SrcType, src_stride, src_bytes, i32, dst_stride, dst_bytes, src.len),
|
||||
f32 => conv.floatToSigned(SrcType, src_stride, src_bytes, i32, dst_stride, dst_bytes, src.len),
|
||||
else => unreachable,
|
||||
},
|
||||
.f32 => switch (SrcType) {
|
||||
f32 => @memcpy(@as([*]f32, @ptrCast(@alignCast(dst)))[0..dst_len], src),
|
||||
u8 => conv.unsignedToFloat(SrcType, src, f32, @as([*]f32, @ptrCast(@alignCast(dst)))[0..dst_len]),
|
||||
i8, i16, i24, i32 => conv.signedToFloat(SrcType, src, f32, @as([*]f32, @ptrCast(@alignCast(dst)))[0..dst_len]),
|
||||
f32 => @memcpy(dst_bytes, src_bytes),
|
||||
u8 => conv.unsignedToFloat(SrcType, src_stride, src_bytes, f32, dst_stride, dst_bytes, src.len),
|
||||
i8, i16, i24, i32 => conv.signedToFloat(SrcType, src_stride, src_bytes, f32, dst_stride, dst_bytes, src.len),
|
||||
else => unreachable,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn convertFrom(comptime DestType: type, dst: []DestType, src_format: Format, src: []const u8) void {
|
||||
const src_len = src.len / src_format.size();
|
||||
std.debug.assert(src_len == dst.len);
|
||||
pub fn convertFrom(comptime DstType: type, dst: []DstType, src_format: Format, src_bytes: []const u8) void {
|
||||
const src_stride = src_format.size();
|
||||
const dst_stride = @bitSizeOf(DstType) / 8;
|
||||
const dst_bytes = @as([*]u8, @ptrCast(@alignCast(dst)))[0 .. dst.len * dst_stride];
|
||||
std.debug.assert(@bitSizeOf(DstType) % 8 == 0);
|
||||
std.debug.assert(src_bytes.len / src_stride == dst.len);
|
||||
|
||||
return switch (src_format) {
|
||||
.u8 => switch (DestType) {
|
||||
u8 => @memcpy(dst, @as([*]const u8, @ptrCast(@alignCast(src)))[0..src_len]),
|
||||
i8, i16, i24, i32 => conv.unsignedToSigned(u8, @as([*]const u8, @ptrCast(@alignCast(src)))[0..src_len], DestType, dst),
|
||||
f32 => conv.unsignedToFloat(u8, @as([*]const u8, @ptrCast(@alignCast(src)))[0..src_len], DestType, dst),
|
||||
.u8 => switch (DstType) {
|
||||
u8 => @memcpy(dst_bytes, src_bytes),
|
||||
i8, i16, i24, i32 => conv.unsignedToSigned(u8, src_stride, src_bytes, DstType, dst_stride, dst_bytes, dst.len),
|
||||
f32 => conv.unsignedToFloat(u8, src_stride, src_bytes, DstType, dst_stride, dst_bytes, dst.len),
|
||||
else => unreachable,
|
||||
},
|
||||
.i16 => switch (DestType) {
|
||||
i16 => @memcpy(dst, @as([*]const i16, @ptrCast(@alignCast(src)))[0..src_len]),
|
||||
u8 => conv.signedToUnsigned(i16, @as([*]const i16, @ptrCast(@alignCast(src)))[0..src_len], DestType, dst),
|
||||
i8, i24, i32 => conv.signedToSigned(i16, @as([*]const i16, @ptrCast(@alignCast(src)))[0..src_len], DestType, dst),
|
||||
f32 => conv.signedToFloat(i16, @as([*]const i16, @ptrCast(@alignCast(src)))[0..src_len], DestType, dst),
|
||||
.i16 => switch (DstType) {
|
||||
i16 => @memcpy(dst_bytes, src_bytes),
|
||||
u8 => conv.signedToUnsigned(i16, src_stride, src_bytes, DstType, dst_stride, dst_bytes, dst.len),
|
||||
i8, i24, i32 => conv.signedToSigned(i16, src_stride, src_bytes, DstType, dst_stride, dst_bytes, dst.len),
|
||||
f32 => conv.signedToFloat(i16, src_stride, src_bytes, DstType, dst_stride, dst_bytes, dst.len),
|
||||
else => unreachable,
|
||||
},
|
||||
// TODO(i24)
|
||||
// .i24 => switch (DestType) {
|
||||
// i24 => @memcpy(dst, @as([*]const i24, @ptrCast(@alignCast(src)))[0..src_len]),
|
||||
// u8 => conv.signedToUnsigned(i24, @as([*]const i24, @ptrCast(@alignCast(src)))[0..src_len], DestType, dst),
|
||||
// i8, i16, i32 => conv.signedToSigned(i24, @as([*]const i24, @ptrCast(@alignCast(src)))[0..src_len], DestType, dst),
|
||||
// f32 => conv.signedToFloat(i24, @as([*]const i24, @ptrCast(@alignCast(src)))[0..src_len], DestType, dst),
|
||||
// else => unreachable,
|
||||
// },
|
||||
.i32 => switch (DestType) {
|
||||
i32 => @memcpy(dst, @as([*]const i32, @ptrCast(@alignCast(src)))[0..src_len]),
|
||||
u8 => conv.signedToUnsigned(i32, @as([*]const i32, @ptrCast(@alignCast(src)))[0..src_len], DestType, dst),
|
||||
i8, i16, i24 => conv.signedToSigned(i32, @as([*]const i32, @ptrCast(@alignCast(src)))[0..src_len], DestType, dst),
|
||||
f32 => conv.signedToFloat(i32, @as([*]const i32, @ptrCast(@alignCast(src)))[0..src_len], DestType, dst),
|
||||
.i24 => switch (DstType) {
|
||||
i24 => @memcpy(dst_bytes, src_bytes),
|
||||
u8 => conv.signedToUnsigned(i24, src_stride, src_bytes, DstType, dst_stride, dst_bytes, dst.len),
|
||||
i8, i16, i32 => conv.signedToSigned(i24, src_stride, src_bytes, DstType, dst_stride, dst_bytes, dst.len),
|
||||
f32 => conv.signedToFloat(i24, src_stride, src_bytes, DstType, dst_stride, dst_bytes, dst.len),
|
||||
else => unreachable,
|
||||
},
|
||||
.f32 => switch (DestType) {
|
||||
f32 => @memcpy(dst, @as([*]const f32, @ptrCast(@alignCast(src)))[0..src_len]),
|
||||
u8 => conv.floatToUnsigned(f32, @as([*]const f32, @ptrCast(@alignCast(src)))[0..src_len], DestType, dst),
|
||||
i8, i16, i24, i32 => conv.floatToSigned(f32, @as([*]const f32, @ptrCast(@alignCast(src)))[0..src_len], DestType, dst),
|
||||
.i32 => switch (DstType) {
|
||||
i32 => @memcpy(dst_bytes, src_bytes),
|
||||
u8 => conv.signedToUnsigned(i32, src_stride, src_bytes, DstType, dst_stride, dst_bytes, dst.len),
|
||||
i8, i16, i24 => conv.signedToSigned(i32, src_stride, src_bytes, DstType, dst_stride, dst_bytes, dst.len),
|
||||
f32 => conv.signedToFloat(i32, src_stride, src_bytes, DstType, dst_stride, dst_bytes, dst.len),
|
||||
else => unreachable,
|
||||
},
|
||||
.f32 => switch (DstType) {
|
||||
f32 => @memcpy(dst_bytes, src_bytes),
|
||||
u8 => conv.floatToUnsigned(f32, src_stride, src_bytes, DstType, dst_stride, dst_bytes, dst.len),
|
||||
i8, i16, i24, i32 => conv.floatToSigned(f32, src_stride, src_bytes, DstType, dst_stride, dst_bytes, dst.len),
|
||||
else => unreachable,
|
||||
},
|
||||
};
|
||||
|
|
@ -418,6 +422,7 @@ pub const Device = struct {
|
|||
capture,
|
||||
};
|
||||
|
||||
// TODO: don't call this in backends. let the user use it
|
||||
pub fn preferredFormat(device: Device, format: ?Format) Format {
|
||||
if (format) |f| {
|
||||
for (device.formats) |fmt| if (f == fmt) return fmt;
|
||||
|
|
@ -455,8 +460,7 @@ pub const ChannelPosition = enum {
|
|||
pub const Format = enum {
|
||||
u8,
|
||||
i16,
|
||||
// TODO(i24): Uncomment when https://github.com/hexops/mach/issues/1152 is fixed
|
||||
// i24 = 2,
|
||||
i24,
|
||||
i32,
|
||||
f32,
|
||||
|
||||
|
|
@ -464,8 +468,7 @@ pub const Format = enum {
|
|||
return switch (format) {
|
||||
.u8 => 1,
|
||||
.i16 => 2,
|
||||
// TODO(i24)
|
||||
// .i24 => 3,
|
||||
.i24 => 3,
|
||||
.i32, .f32 => 4,
|
||||
};
|
||||
}
|
||||
|
|
@ -474,8 +477,7 @@ pub const Format = enum {
|
|||
return switch (format) {
|
||||
.u8 => 1,
|
||||
.i16 => 2,
|
||||
// TODO(i24)
|
||||
// .i24 => 3,
|
||||
.i24 => 3,
|
||||
.i32, .f32 => 4,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -746,8 +746,7 @@ fn performOperation(main_loop: *c.pa_threaded_mainloop, op: ?*c.pa_operation) vo
|
|||
pub const available_formats = &[_]main.Format{
|
||||
.u8,
|
||||
.i16,
|
||||
// TODO(i24)
|
||||
// .i24,
|
||||
.i24,
|
||||
.i32,
|
||||
.f32,
|
||||
};
|
||||
|
|
@ -783,8 +782,7 @@ pub fn toPAFormat(format: main.Format) c.pa_sample_format_t {
|
|||
return switch (format) {
|
||||
.u8 => c.PA_SAMPLE_U8,
|
||||
.i16 => if (is_little) c.PA_SAMPLE_S16LE else c.PA_SAMPLE_S16BE,
|
||||
// TODO(i24)
|
||||
// .i24 => if (is_little) c.PA_SAMPLE_S24LE else c.PA_SAMPLE_S24LE,
|
||||
.i24 => if (is_little) c.PA_SAMPLE_S24LE else c.PA_SAMPLE_S24LE,
|
||||
.i32 => if (is_little) c.PA_SAMPLE_S32LE else c.PA_SAMPLE_S32BE,
|
||||
.f32 => if (is_little) c.PA_SAMPLE_FLOAT32LE else c.PA_SAMPLE_FLOAT32BE,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -677,12 +677,7 @@ pub const Context = struct {
|
|||
|
||||
fn toSubFormat(format: main.Format) win32.Guid {
|
||||
return switch (format) {
|
||||
.u8,
|
||||
.i16,
|
||||
// TODO(i24)
|
||||
// .i24,
|
||||
.i32,
|
||||
=> win32.CLSID_KSDATAFORMAT_SUBTYPE_PCM.*,
|
||||
.u8, .i16, .i24, .i32 => win32.CLSID_KSDATAFORMAT_SUBTYPE_PCM.*,
|
||||
.f32 => win32.CLSID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT.*,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue