Skip to content

Commit 22c635c

Browse files
authored
Adding extended precision ByteVector conversion (#245)
Using extended precision conversion to get any possible AIFF sample rate
1 parent a3b5676 commit 22c635c

File tree

2 files changed

+41
-51
lines changed

2 files changed

+41
-51
lines changed

src/TaglibSharp/Aiff/StreamHeader.cs

Lines changed: 3 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public struct StreamHeader : IAudioCodec, ILosslessAudioCodec
6666
/// </summary>
6767
/// <remarks>
6868
/// This value is stored in bytes (17-26).
69-
/// the sample rate at which the sound is to be played back,
69+
/// the sample rate at which the sound is to be played back,
7070
/// in sample frames per second
7171
/// </remarks>
7272
readonly ulong sample_rate;
@@ -120,7 +120,7 @@ public struct StreamHeader : IAudioCodec, ILosslessAudioCodec
120120
/// </exception>
121121
/// <exception cref="CorruptFileException">
122122
/// <paramref name="data" /> does not begin with <see
123-
/// cref="FileIdentifier" />
123+
/// cref="FileIdentifier" />
124124
/// </exception>
125125
public StreamHeader (ByteVector data, long streamLength)
126126
{
@@ -138,54 +138,7 @@ public StreamHeader (ByteVector data, long streamLength)
138138
channels = data.Mid (8, 2).ToUShort (true);
139139
total_frames = data.Mid (10, 4).ToULong (true);
140140
bits_per_sample = data.Mid (14, 2).ToUShort (true);
141-
142-
ByteVector sample_rate_indicator = data.Mid (17, 1);
143-
ulong sample_rate_tmp = data.Mid (18, 2).ToULong (true);
144-
sample_rate = 44100; // Set 44100 as default sample rate
145-
146-
// The following are combinations that iTunes 8 encodes to.
147-
// There may be other combinations in the field, but i couldn't test them.
148-
switch (sample_rate_tmp) {
149-
case 44100:
150-
if (sample_rate_indicator == 0x0E) {
151-
sample_rate = 44100;
152-
} else if (sample_rate_indicator == 0x0D) {
153-
sample_rate = 22050;
154-
} else if (sample_rate_indicator == 0x0C) {
155-
sample_rate = 11025;
156-
}
157-
break;
158-
159-
case 48000:
160-
if (sample_rate_indicator == 0x0E) {
161-
sample_rate = 48000;
162-
} else if (sample_rate_indicator == 0x0D) {
163-
sample_rate = 24000;
164-
}
165-
break;
166-
167-
case 64000:
168-
if (sample_rate_indicator == 0x0D) {
169-
sample_rate = 32000;
170-
} else if (sample_rate_indicator == 0x0C) {
171-
sample_rate = 16000;
172-
} else if (sample_rate_indicator == 0x0B) {
173-
sample_rate = 8000;
174-
}
175-
break;
176-
177-
case 44510:
178-
if (sample_rate_indicator == 0x0D) {
179-
sample_rate = 22255;
180-
}
181-
break;
182-
183-
case 44508:
184-
if (sample_rate_indicator == 0x0C) {
185-
sample_rate = 11127;
186-
}
187-
break;
188-
}
141+
sample_rate = (ulong)data.Mid (16, 10).ToExtendedPrecision ();
189142
}
190143

191144
#endregion

src/TaglibSharp/ByteVector.cs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,7 @@ public bool ContainsAt (ByteVector pattern, int offset, int patternOffset, int p
757757
patternLength = pattern.Count;
758758
}
759759

760-
// do some sanity checking -- all of these things are
760+
// do some sanity checking -- all of these things are
761761
// needed for the search to be valid
762762
if (patternLength > data.Count ||
763763
offset >= data.Count ||
@@ -1398,6 +1398,43 @@ public double ToDouble ()
13981398
return ToDouble (true);
13991399
}
14001400

1401+
/// <summary>
1402+
/// Converts the first 10 bytes of the current instance to an IEEE
1403+
/// 754 80-bit extended precision floating point number, expressed
1404+
/// as a <see cref="double"/>.
1405+
/// </summary>
1406+
/// <returns>
1407+
/// A <see cref="double"/> value containing the value read from the
1408+
/// current instance.
1409+
/// </returns>
1410+
public double ToExtendedPrecision ()
1411+
{
1412+
int exponent = ((this[0] & 0x7F) << 8) | this[1];
1413+
ulong hiMantissa = ((ulong)this[2] << 24)
1414+
| ((ulong)this[3] << 16)
1415+
| ((ulong)this[4] << 8)
1416+
| this[5];
1417+
ulong loMantissa = ((ulong)this[6] << 24)
1418+
| ((ulong)this[7] << 16)
1419+
| ((ulong)this[8] << 8)
1420+
| this[9];
1421+
1422+
double f;
1423+
if (exponent == 0 && hiMantissa == 0 && loMantissa == 0) {
1424+
f = 0;
1425+
} else {
1426+
if (exponent == 0x7FFF) {
1427+
f = double.PositiveInfinity;
1428+
} else {
1429+
exponent -= 16383;
1430+
f = hiMantissa * Math.Pow (2, exponent -= 31);
1431+
f += loMantissa * Math.Pow (2, exponent -= 32);
1432+
}
1433+
}
1434+
1435+
return (this[0] & 0x80) != 0 ? -f : f;
1436+
}
1437+
14011438
/// <summary>
14021439
/// Converts a portion of the current instance to a <see
14031440
/// cref="string"/> object using a specified encoding.

0 commit comments

Comments
 (0)