support inverting dop output
Adrian Smith
9 years ago
57 | 57 | return false; |
58 | 58 | } |
59 | 59 | |
60 | // update the dop marker for frames in the output buffer | |
60 | // update the dop marker and potentially invert polarity for frames in the output buffer | |
61 | 61 | // performaned on all output including silence to maintain marker phase consitency |
62 | void update_dop_marker(u32_t *ptr, frames_t frames) { | |
62 | void update_dop(u32_t *ptr, frames_t frames, bool invert) { | |
63 | 63 | static u32_t marker = 0x05; |
64 | while (frames--) { | |
65 | u32_t scaled_marker = marker << 24; | |
66 | *ptr = (*ptr & 0x00FFFFFF) | scaled_marker; | |
67 | ++ptr; | |
68 | *ptr = (*ptr & 0x00FFFFFF) | scaled_marker; | |
69 | ++ptr; | |
70 | marker = ( 0x05 + 0xFA ) - marker; | |
64 | if (!invert) { | |
65 | while (frames--) { | |
66 | u32_t scaled_marker = marker << 24; | |
67 | *ptr = (*ptr & 0x00FFFFFF) | scaled_marker; | |
68 | ++ptr; | |
69 | *ptr = (*ptr & 0x00FFFFFF) | scaled_marker; | |
70 | ++ptr; | |
71 | marker = ( 0x05 + 0xFA ) - marker; | |
72 | } | |
73 | } else { | |
74 | while (frames--) { | |
75 | u32_t scaled_marker = marker << 24; | |
76 | *ptr = ((~(*ptr)) & 0x00FFFFFF) | scaled_marker; | |
77 | ++ptr; | |
78 | *ptr = ((~(*ptr)) & 0x00FFFFFF) | scaled_marker; | |
79 | ++ptr; | |
80 | marker = ( 0x05 + 0xFA ) - marker; | |
81 | } | |
71 | 82 | } |
72 | 83 | } |
73 | 84 |
46 | 46 | |
47 | 47 | s32_t cross_gain_in = 0, cross_gain_out = 0; s32_t *cross_ptr = NULL; |
48 | 48 | |
49 | s32_t gainL = output.polarity * (output.current_replay_gain ? gain(output.gainL, output.current_replay_gain) : output.gainL); | |
50 | s32_t gainR = output.polarity * (output.current_replay_gain ? gain(output.gainR, output.current_replay_gain) : output.gainR); | |
49 | s32_t gainL = output.current_replay_gain ? gain(output.gainL, output.current_replay_gain) : output.gainL; | |
50 | s32_t gainR = output.current_replay_gain ? gain(output.gainR, output.current_replay_gain) : output.gainR; | |
51 | ||
52 | if (output.invert) { gainL = -gainL; gainR = -gainR; } | |
51 | 53 | |
52 | 54 | frames = _buf_used(outputbuf) / BYTES_PER_FRAME; |
53 | 55 | silence = false; |
217 | 219 | cur_f = dur_f - cur_f; |
218 | 220 | } |
219 | 221 | fade_gain = to_gain((float)cur_f / (float)dur_f); |
220 | gainL = output.polarity * gain(gainL, fade_gain); | |
221 | gainR = output.polarity * gain(gainR, fade_gain); | |
222 | gainL = gain(gainL, fade_gain); | |
223 | gainR = gain(gainR, fade_gain); | |
224 | if (output.invert) { gainL = -gainL; gainR = -gainR; } | |
222 | 225 | } |
223 | 226 | if (output.fade_dir == FADE_CROSS) { |
224 | 227 | // cross fade requires special treatment - performed later based on these values |
232 | 235 | if (output.next_replay_gain) { |
233 | 236 | cross_gain_in = gain(cross_gain_in, output.next_replay_gain); |
234 | 237 | } |
235 | gainL = output.polarity * output.gainL; | |
236 | gainR = output.polarity * output.gainR; | |
238 | gainL = output.gainL; | |
239 | gainR = output.gainR; | |
240 | if (output.invert) { gainL = -gainL; gainR = -gainR; } | |
237 | 241 | cross_ptr = (s32_t *)(output.fade_end + cur_f * BYTES_PER_FRAME); |
238 | 242 | } else { |
239 | 243 | LOG_INFO("unable to continue crossfade - too few samples"); |
367 | 371 | output.state = idle ? OUTPUT_OFF: OUTPUT_STOPPED; |
368 | 372 | output.device = device; |
369 | 373 | output.fade = FADE_INACTIVE; |
370 | output.polarity = 1; | |
374 | output.invert = false; | |
371 | 375 | output.error_opening = false; |
372 | 376 | output.idle_to = (u32_t) idle; |
373 | 377 |
543 | 543 | if (silence) { |
544 | 544 | inputptr = (s32_t *) silencebuf_dop; |
545 | 545 | } |
546 | update_dop_marker((u32_t *) inputptr, out_frames); | |
546 | update_dop((u32_t *) inputptr, out_frames, output.invert); | |
547 | 547 | } |
548 | 548 | ) |
549 | 549 |
313 | 313 | |
314 | 314 | IF_DSD( |
315 | 315 | if (output.dop) { |
316 | update_dop_marker((u32_t *) outputbuf->readp, out_frames); | |
316 | update_dop((u32_t *) outputbuf->readp, out_frames, output.invert); | |
317 | 317 | } |
318 | 318 | ) |
319 | 319 | |
326 | 326 | IF_DSD( |
327 | 327 | if (output.dop) { |
328 | 328 | buf = silencebuf_dop; |
329 | update_dop_marker((u32_t *) buf, out_frames); | |
329 | update_dop((u32_t *) buf, out_frames, output.invert); | |
330 | 330 | } |
331 | 331 | ) |
332 | 332 |
66 | 66 | if (silence) { |
67 | 67 | obuf = silencebuf_dop; |
68 | 68 | } |
69 | update_dop_marker((u32_t *)obuf, out_frames); | |
69 | update_dop((u32_t *)obuf, out_frames, output.invert); | |
70 | 70 | } |
71 | 71 | ) |
72 | 72 |
352 | 352 | output.next_replay_gain = unpackN(&strm->replay_gain); |
353 | 353 | output.fade_mode = strm->transition_type - '0'; |
354 | 354 | output.fade_secs = strm->transition_period; |
355 | output.polarity = strm->flags & 0x03 ? -1 : 1; | |
355 | output.invert = (strm->flags & 0x03) == 0x03; | |
356 | 356 | LOG_DEBUG("set fade mode: %u", output.fade_mode); |
357 | 357 | UNLOCK_O; |
358 | 358 | } |
560 | 560 | u8_t *track_start; // set in decode thread |
561 | 561 | u32_t gainL; // set by slimproto |
562 | 562 | u32_t gainR; // set by slimproto |
563 | int polarity; // set by slimproto (1 or -1) | |
563 | bool invert; // set by slimproto | |
564 | 564 | u32_t next_replay_gain; // set by slimproto |
565 | 565 | unsigned threshold; // set by slimproto |
566 | 566 | fade_state fade; |
633 | 633 | // dop.c |
634 | 634 | #if DSD |
635 | 635 | bool is_flac_dop(u32_t *lptr, u32_t *rptr, frames_t frames); |
636 | void update_dop_marker(u32_t *ptr, frames_t frames); | |
636 | void update_dop(u32_t *ptr, frames_t frames, bool invert); | |
637 | 637 | void dop_silence_frames(u32_t *ptr, frames_t frames); |
638 | 638 | void dop_init(bool enable, unsigned delay); |
639 | 639 | #endif |