Code Coverage Report for src/util/decode-frame.c


Hit Total Coverage
Lines: 59 59 100.0%
Branches: 334 334 100.0%

1 /*
2 * libnogg: a decoder library for Ogg Vorbis streams
3 * Copyright (c) 2014-2024 Andrew Church <achurch@achurch.org>
4 *
5 * This software may be copied and redistributed under certain conditions;
6 * see the file "COPYING" in the source code distribution for details.
7 * NO WARRANTY is provided with this software.
8 */
9
10 #include "include/nogg.h"
11 #include "src/common.h"
12 #include "src/util/decode-frame.h"
13 #include "src/util/float-to-int16.h"
14 #include "src/x86.h"
15
16 #include <string.h>
17
18 #ifdef ENABLE_ASM_ARM_NEON
19 # include <arm_neon.h>
20 #endif
21
22 /*************************************************************************/
23 /**************************** Helper routines ****************************/
24 /*************************************************************************/
25
26 /**
27 * interleave: Interleave source channels into a destination buffer.
28 *
29 * [Parameters]
30 * dest: Destination buffer pointer.
31 * src: Source buffer pointer array.
32 * channels: Number of channels.
33 * samples: Number of samples per channel.
34 */
35 static void interleave(float *dest, float **src, int channels, int samples)
36 {
37 (18/18) for (int i = 0; i < samples; i++) {
38 (18/18) for (int c = 0; c < channels; c++) {
39 *dest++ = src[c][i];
40 }
41 }
42 }
43
44 /*-----------------------------------------------------------------------*/
45
46 /**
47 * interleave_2: Interleave two source channels into a destination buffer.
48 * Specialization of interleave() for channels==2.
49 *
50 * [Parameters]
51 * dest: Destination buffer pointer.
52 * src: Source buffer pointer array.
53 * samples: Number of samples per channel.
54 */
55 static void interleave_2(float *dest, float **src, int samples)
56 {
57 const float *src0 = src[0];
58 const float *src1 = src[1];
59
60 #if defined(ENABLE_ASM_ARM_NEON)
61 for (; samples >= 4; src0 += 4, src1 += 4, dest += 8, samples -= 4) {
62 float32x4x2_t data;
63 data.val[0] = vld1q_f32(src0);
64 data.val[1] = vld1q_f32(src1);
65 vst2q_f32(dest, data);
66 }
67 #elif defined(ENABLE_ASM_X86_AVX2)
68 for (; samples >= 8; src0 += 8, src1 += 8, dest += 16, samples -= 8) {
69 const __m256i data0 = _mm256_load_si256((const void *)src0);
70 const __m256i data1 = _mm256_load_si256((const void *)src1);
71 const __m256i sample0145 = _mm256_unpacklo_epi32(data0, data1);
72 const __m256i sample2367 = _mm256_unpackhi_epi32(data0, data1);
73 _mm256_store_si256((void *)(dest+0), _mm256_permute2x128_si256(
74 sample0145, sample2367, 0x20));
75 _mm256_store_si256((void *)(dest+8), _mm256_permute2x128_si256(
76 sample0145, sample2367, 0x31));
77 }
78 #elif defined(ENABLE_ASM_X86_SSE2)
79 (10/10) for (; samples >= 4; src0 += 4, src1 += 4, dest += 8, samples -= 4) {
80 const __m128i data0 = _mm_load_si128((const void *)src0);
81 const __m128i data1 = _mm_load_si128((const void *)src1);
82 _mm_store_si128((void *)(dest+0), _mm_unpacklo_epi32(data0, data1));
83 _mm_store_si128((void *)(dest+4), _mm_unpackhi_epi32(data0, data1));
84 }
85 #endif
86
87 (18/18) for (int i = 0; i < samples; i++) {
88 dest[i*2+0] = src0[i];
89 dest[i*2+1] = src1[i];
90 }
91 }
92
93 /*************************************************************************/
94 /************************** Interface routines ***************************/
95 /*************************************************************************/
96
97 vorbis_error_t decode_frame(vorbis_t *handle, const void *packet,
98 int32_t packet_len)
99 {
100 handle->frame_pos += handle->decode_buf_len;
101 handle->decode_buf_pos = 0;
102 handle->decode_buf_len = 0;
103
104 (void) stb_vorbis_get_error(handle->decoder); // Clear any pending error.
105 float **outputs;
106 int samples = 0;
107 (18/18) if (handle->packet_mode) {
108 ASSERT(packet != NULL);
109 ASSERT(packet_len > 0);
110 (void) stb_vorbis_decode_packet_float(handle->decoder, packet,
111 packet_len, &outputs, &samples);
112 } else {
113 do {
114 stb_vorbis_reset_eof(handle->decoder);
115 (18/18) if (!stb_vorbis_get_frame_float(handle->decoder,
116 &outputs, &samples)) {
117 break;
118 }
119 handle->frame_pos = stb_vorbis_tell_pcm(handle->decoder) - samples;
120 (18/18) } while (samples == 0);
121 }
122
123 (18/18) if (samples > 0) {
124 const int channels = handle->channels;
125 (18/18) if (handle->read_int16_only) {
126 int16_t *decode_buf = handle->decode_buf;
127 (18/18) if (channels == 1) {
128 float_to_int16(decode_buf, outputs[0], samples);
129 (18/18) } else if (channels == 2) {
130 float_to_int16_interleave_2(decode_buf, outputs[0],
131 outputs[1], samples);
132 } else {
133 float_to_int16_interleave(decode_buf, outputs, channels,
134 samples);
135 }
136 } else {
137 float *decode_buf = handle->decode_buf;
138 (18/18) if (channels == 1) {
139 memcpy(decode_buf, outputs[0], sizeof(*decode_buf) * samples);
140 (18/18) } else if (channels == 2) {
141 interleave_2(decode_buf, outputs, samples);
142 } else {
143 interleave(decode_buf, outputs, channels, samples);
144 }
145 }
146 }
147 handle->decode_buf_len = samples;
148
149 const STBVorbisError stb_error = stb_vorbis_get_error(handle->decoder);
150 (36/36) if (samples == 0 && stb_error == VORBIS__no_error) {
151 return VORBIS_ERROR_STREAM_END;
152 (18/18) } else if (stb_error == VORBIS_invalid_packet
153 (18/18) || stb_error == VORBIS_continued_packet_flag_invalid
154 (18/18) || stb_error == VORBIS_wrong_page_number) {
155 return VORBIS_ERROR_DECODE_RECOVERED;
156 (18/18) } else if (stb_error != VORBIS__no_error) {
157 return VORBIS_ERROR_DECODE_FAILED;
158 } else {
159 return VORBIS_NO_ERROR;
160 }
161 }
162
163 /*************************************************************************/
164 /*************************************************************************/