|
36 | 36 |
|
37 | 37 | #define SAMPLE_SIZE(sample_info) (sample_info.bits_per_sample * sample_info.channel / 8) |
38 | 38 | #define SAMPLE_SIZE_PER_SECOND(sample_info) (sample_info.sample_rate * SAMPLE_SIZE(sample_info)) |
39 | | -#define SAME_SAMPLE_INFO(a, b) (a.sample_rate == b.sample_rate && a.bits_per_sample == b.bits_per_sample && a.channel == b.channel) |
40 | 39 | #define AAC_FRAME_SAMPLES (1024) |
41 | 40 | #define ELEMS(arr) sizeof(arr)/sizeof(arr[0]) |
42 | 41 | #define DEFAULT_MIXER_INTERVAL (20) |
@@ -1102,3 +1101,136 @@ int audio_render_with_no_pool(int write_count) |
1102 | 1101 | } |
1103 | 1102 | return success ? 0 : -1; |
1104 | 1103 | } |
| 1104 | + |
| 1105 | + |
| 1106 | +static int render_solo_verify_hdlr(uint8_t *pcm_data, uint32_t len, void *ctx) |
| 1107 | +{ |
| 1108 | + render_out_res_t *res = (render_out_res_t*)ctx; |
| 1109 | + res->actual_samples[0] = pcm_data[0]; |
| 1110 | + res->actual_samples[1] = pcm_data[len - 1]; |
| 1111 | + vTaskDelay(pdMS_TO_TICKS(DEFAULT_MIXER_INTERVAL)); |
| 1112 | + return 0; |
| 1113 | +} |
| 1114 | + |
| 1115 | +int audio_render_dual_stream_solo(int write_count) |
| 1116 | +{ |
| 1117 | + render_out_res_t res = {}; |
| 1118 | + // Force to use mixer |
| 1119 | + esp_audio_render_cfg_t cfg = { |
| 1120 | + .max_stream_num = 2, |
| 1121 | + .out_sample_info = { |
| 1122 | + .sample_rate = 8000, |
| 1123 | + .bits_per_sample = 16, |
| 1124 | + .channel = 2, |
| 1125 | + }, |
| 1126 | + .out_writer = render_solo_verify_hdlr, |
| 1127 | + .out_ctx = &res, |
| 1128 | + }; |
| 1129 | + create_default_pool((esp_gmf_pool_handle_t*)&cfg.pool); |
| 1130 | + esp_audio_render_err_t ret; |
| 1131 | + esp_audio_render_handle_t render = NULL; |
| 1132 | + bool success = false; |
| 1133 | + // Force input and out sample info same to verify data |
| 1134 | + esp_audio_render_sample_info_t in_sample_info = { |
| 1135 | + .sample_rate = 8000, |
| 1136 | + .bits_per_sample = 16, |
| 1137 | + .channel = 2, |
| 1138 | + }; |
| 1139 | + uint8_t actual_data[2]; |
| 1140 | + res.actual_samples = actual_data; |
| 1141 | + int frame_size = DEFAULT_MIXER_INTERVAL * in_sample_info.sample_rate / 1000 * SAMPLE_SIZE(in_sample_info); |
| 1142 | + uint8_t *write_data = (uint8_t*)calloc(1, frame_size); |
| 1143 | + do { |
| 1144 | + if (write_data == NULL) { |
| 1145 | + BREAK_ON_FAIL(ESP_AUDIO_RENDER_ERR_NO_MEM); |
| 1146 | + } |
| 1147 | + ret = esp_audio_render_create(&cfg, &render); |
| 1148 | + BREAK_ON_FAIL(ret); |
| 1149 | + |
| 1150 | + ret = esp_audio_render_set_event_cb(render, render_event_hdlr, &res); |
| 1151 | + BREAK_ON_FAIL(ret); |
| 1152 | + |
| 1153 | + esp_audio_render_stream_handle_t stream[2] = {NULL}; |
| 1154 | + esp_audio_render_stream_get(render, ESP_AUDIO_RENDER_FIRST_STREAM, &stream[0]); |
| 1155 | + BREAK_ON_FAIL(stream[0] == NULL); |
| 1156 | + esp_audio_render_stream_get(render, ESP_AUDIO_RENDER_SECOND_STREAM, &stream[1]); |
| 1157 | + BREAK_ON_FAIL(stream[1] == NULL); |
| 1158 | + |
| 1159 | + ret = esp_audio_render_stream_open(stream[0], &in_sample_info); |
| 1160 | + BREAK_ON_FAIL(ret); |
| 1161 | + ret = esp_audio_render_stream_open(stream[1], &in_sample_info); |
| 1162 | + BREAK_ON_FAIL(ret); |
| 1163 | + uint8_t stream_value[2] = {16, 48}; |
| 1164 | + // Wait for enter stable status |
| 1165 | + for (int i = 0; i < 20; i++) { |
| 1166 | + ret = esp_audio_render_stream_write(stream[0], write_data, frame_size); |
| 1167 | + BREAK_ON_FAIL(ret); |
| 1168 | + } |
| 1169 | + vTaskDelay(pdMS_TO_TICKS(DEFAULT_MIXER_INTERVAL)); |
| 1170 | + ret = esp_audio_render_set_solo_stream(render, ESP_AUDIO_RENDER_FIRST_STREAM); |
| 1171 | + BREAK_ON_FAIL(ret); |
| 1172 | + |
| 1173 | + memset(write_data, stream_value[0], frame_size); |
| 1174 | + ret = esp_audio_render_stream_write(stream[0], write_data, frame_size); |
| 1175 | + BREAK_ON_FAIL(ret); |
| 1176 | + memset(write_data, stream_value[1], frame_size); |
| 1177 | + ret = esp_audio_render_stream_write(stream[1], write_data, frame_size); |
| 1178 | + BREAK_ON_FAIL(ret); |
| 1179 | + if (actual_data[0] != stream_value[0] || actual_data[1] != stream_value[0]) { |
| 1180 | + ESP_LOGE(TAG, "First stream expect %d but get %d-%d", stream_value[0], actual_data[0], actual_data[1]); |
| 1181 | + ret = -1; |
| 1182 | + BREAK_ON_FAIL(ret); |
| 1183 | + } |
| 1184 | + |
| 1185 | + ret = esp_audio_render_set_solo_stream(render, ESP_AUDIO_RENDER_SECOND_STREAM); |
| 1186 | + BREAK_ON_FAIL(ret); |
| 1187 | + memset(write_data, stream_value[1], frame_size); |
| 1188 | + ret = esp_audio_render_stream_write(stream[1], write_data, frame_size); |
| 1189 | + BREAK_ON_FAIL(ret); |
| 1190 | + memset(write_data, stream_value[0], frame_size); |
| 1191 | + ret = esp_audio_render_stream_write(stream[0], write_data, frame_size); |
| 1192 | + BREAK_ON_FAIL(ret); |
| 1193 | + if (actual_data[0] != stream_value[1] || actual_data[1] != stream_value[1]) { |
| 1194 | + ESP_LOGE(TAG, "Second stream expect %d but get %d-%d", stream_value[1], actual_data[0], actual_data[1]); |
| 1195 | + ret = -1; |
| 1196 | + BREAK_ON_FAIL(ret); |
| 1197 | + } |
| 1198 | + |
| 1199 | + ret = esp_audio_render_set_solo_stream(render, ESP_AUDIO_RENDER_ALL_STREAM); |
| 1200 | + BREAK_ON_FAIL(ret); |
| 1201 | + |
| 1202 | + for (int j = 0; j < 2; j++) { |
| 1203 | + for (int i = 0; i < 2; i++) { |
| 1204 | + memset(write_data, stream_value[i], frame_size); |
| 1205 | + ret = esp_audio_render_stream_write(stream[i], write_data, frame_size); |
| 1206 | + BREAK_ON_FAIL(ret); |
| 1207 | + } |
| 1208 | + } |
| 1209 | + vTaskDelay(pdMS_TO_TICKS(DEFAULT_MIXER_INTERVAL)); |
| 1210 | + uint8_t expected = (stream_value[0] + stream_value[1]) / 2; |
| 1211 | + #define IS_EXPECT(a, b) (a == b || a == b - 1) |
| 1212 | + if (!IS_EXPECT(actual_data[0], expected) || !IS_EXPECT(actual_data[1], expected)) { |
| 1213 | + ESP_LOGE(TAG, "Mixed stream expect %d but get %d-%d", expected, actual_data[0], actual_data[1]); |
| 1214 | + ret = -1; |
| 1215 | + BREAK_ON_FAIL(ret); |
| 1216 | + } |
| 1217 | + ret = esp_audio_render_stream_close(stream[0]); |
| 1218 | + BREAK_ON_FAIL(ret); |
| 1219 | + ret = esp_audio_render_stream_close(stream[1]); |
| 1220 | + BREAK_ON_FAIL(ret); |
| 1221 | + // Verify result |
| 1222 | + if (res.is_open == false || res.is_close == false) { |
| 1223 | + ESP_LOGE(TAG, "Failed to verify open:%d close:%d", res.is_open, res.is_close); |
| 1224 | + break; |
| 1225 | + } |
| 1226 | + success = true; |
| 1227 | + } while (0); |
| 1228 | + if (render) { |
| 1229 | + esp_audio_render_destroy(render); |
| 1230 | + } |
| 1231 | + if (write_data) { |
| 1232 | + free(write_data); |
| 1233 | + } |
| 1234 | + destroy_default_pool((esp_gmf_pool_handle_t)cfg.pool); |
| 1235 | + return success ? 0 : -1; |
| 1236 | +} |
0 commit comments