diff options
Diffstat (limited to 'apps/pcmbuf.c')
-rw-r--r-- | apps/pcmbuf.c | 123 |
1 files changed, 56 insertions, 67 deletions
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index e62fc892cc..9bf4c96233 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c | |||
@@ -690,63 +690,16 @@ static inline int32_t clip_sample_16(int32_t sample) | |||
690 | } | 690 | } |
691 | 691 | ||
692 | #ifdef HAVE_CROSSFADE | 692 | #ifdef HAVE_CROSSFADE |
693 | /* Completely process the crossfade fade-out effect with current PCM buffer */ | 693 | /* Find the chunk that's (length) deep in the list. Return the position within |
694 | static void crossfade_process_buffer(size_t fade_in_delay, | 694 | * the chunk, and leave the chunkdesc pointer pointing to the chunk. */ |
695 | size_t fade_out_delay, size_t fade_out_rem) | 695 | static size_t find_chunk(size_t length, struct chunkdesc **chunk) |
696 | { | 696 | { |
697 | if (!crossfade_mixmode) | 697 | while (*chunk && length >= (*chunk)->size) |
698 | { | 698 | { |
699 | /* Fade out the specified amount of the already processed audio */ | 699 | length -= (*chunk)->size; |
700 | size_t total_fade_out = fade_out_rem; | 700 | *chunk = (*chunk)->link; |
701 | size_t fade_out_sample; | ||
702 | struct chunkdesc *fade_out_chunk = crossfade_chunk; | ||
703 | |||
704 | /* Find the right chunk to start fading out */ | ||
705 | fade_out_delay += crossfade_sample * 2; | ||
706 | while (fade_out_delay != 0 && fade_out_delay >= fade_out_chunk->size) | ||
707 | { | ||
708 | fade_out_delay -= fade_out_chunk->size; | ||
709 | fade_out_chunk = fade_out_chunk->link; | ||
710 | } | ||
711 | /* The start sample within the chunk */ | ||
712 | fade_out_sample = fade_out_delay / 2; | ||
713 | |||
714 | while (fade_out_rem > 0) | ||
715 | { | ||
716 | /* Each 1/10 second of audio will have the same fade applied */ | ||
717 | size_t block_rem = MIN(NATIVE_FREQUENCY * 4 / 10, fade_out_rem); | ||
718 | int factor = (fade_out_rem << 8) / total_fade_out; | ||
719 | |||
720 | fade_out_rem -= block_rem; | ||
721 | |||
722 | /* Fade this block */ | ||
723 | while (block_rem > 0 && fade_out_chunk != NULL) | ||
724 | { | ||
725 | /* Fade one sample */ | ||
726 | int16_t *buf = (int16_t *)fade_out_chunk->addr; | ||
727 | int32_t sample = buf[fade_out_sample]; | ||
728 | buf[fade_out_sample++] = (sample * factor) >> 8; | ||
729 | |||
730 | block_rem -= 2; | ||
731 | /* Move to the next chunk as needed */ | ||
732 | if (fade_out_sample * 2 >= fade_out_chunk->size) | ||
733 | { | ||
734 | fade_out_chunk = fade_out_chunk->link; | ||
735 | fade_out_sample = 0; | ||
736 | } | ||
737 | } | ||
738 | } | ||
739 | } | ||
740 | |||
741 | /* Find the right chunk and sample to start fading in */ | ||
742 | fade_in_delay += crossfade_sample * 2; | ||
743 | while (fade_in_delay != 0 && fade_in_delay >= crossfade_chunk->size) | ||
744 | { | ||
745 | fade_in_delay -= crossfade_chunk->size; | ||
746 | crossfade_chunk = crossfade_chunk->link; | ||
747 | } | 701 | } |
748 | crossfade_sample = fade_in_delay / 2; | 702 | return length / 2; |
749 | logf("process done!"); | ||
750 | } | 703 | } |
751 | 704 | ||
752 | /* Initializes crossfader, calculates all necessary parameters and performs | 705 | /* Initializes crossfader, calculates all necessary parameters and performs |
@@ -777,25 +730,19 @@ static void crossfade_start(void) | |||
777 | crossfade_chunk = read_chunk->link; | 730 | crossfade_chunk = read_chunk->link; |
778 | crossfade_sample = 0; | 731 | crossfade_sample = 0; |
779 | 732 | ||
780 | /* Get fade out delay from settings. */ | 733 | /* Get fade out info from settings. */ |
781 | fade_out_delay = | 734 | fade_out_delay = |
782 | NATIVE_FREQUENCY * global_settings.crossfade_fade_out_delay * 4; | 735 | NATIVE_FREQUENCY * global_settings.crossfade_fade_out_delay * 4; |
783 | |||
784 | /* Get fade out duration from settings. */ | ||
785 | fade_out_rem = | 736 | fade_out_rem = |
786 | NATIVE_FREQUENCY * global_settings.crossfade_fade_out_duration * 4; | 737 | NATIVE_FREQUENCY * global_settings.crossfade_fade_out_duration * 4; |
787 | 738 | ||
788 | crossfade_need = fade_out_delay + fade_out_rem; | 739 | crossfade_need = fade_out_delay + fade_out_rem; |
789 | /* We want only to modify the last part of the buffer. */ | 740 | /* We want only to modify the last part of the buffer, so find |
741 | * the right chunk and sample to start the crossfade */ | ||
790 | if (crossfade_rem > crossfade_need) | 742 | if (crossfade_rem > crossfade_need) |
791 | { | 743 | { |
792 | size_t crossfade_extra = crossfade_rem - crossfade_need; | 744 | crossfade_sample = find_chunk(crossfade_rem - crossfade_need, |
793 | while (crossfade_extra > crossfade_chunk->size) | 745 | &crossfade_chunk); |
794 | { | ||
795 | crossfade_extra -= crossfade_chunk->size; | ||
796 | crossfade_chunk = crossfade_chunk->link; | ||
797 | } | ||
798 | crossfade_sample = crossfade_extra / 2; | ||
799 | } | 746 | } |
800 | /* Truncate fade out duration if necessary. */ | 747 | /* Truncate fade out duration if necessary. */ |
801 | else if (crossfade_rem < crossfade_need) | 748 | else if (crossfade_rem < crossfade_need) |
@@ -810,7 +757,46 @@ static void crossfade_start(void) | |||
810 | } | 757 | } |
811 | } | 758 | } |
812 | 759 | ||
813 | /* Get also fade in duration and delays from settings. */ | 760 | /* Completely process the crossfade fade-out effect with current PCM buffer */ |
761 | if (!crossfade_mixmode) | ||
762 | { | ||
763 | /* Fade out the specified amount of the already processed audio */ | ||
764 | size_t total_fade_out = fade_out_rem; | ||
765 | size_t fade_out_sample; | ||
766 | struct chunkdesc *fade_out_chunk = crossfade_chunk; | ||
767 | |||
768 | /* Find the right chunk and sample to start fading out */ | ||
769 | fade_out_delay += crossfade_sample * 2; | ||
770 | fade_out_sample = find_chunk(fade_out_delay, &fade_out_chunk); | ||
771 | |||
772 | while (fade_out_rem > 0) | ||
773 | { | ||
774 | /* Each 1/10 second of audio will have the same fade applied */ | ||
775 | size_t block_rem = MIN(NATIVE_FREQUENCY * 4 / 10, fade_out_rem); | ||
776 | int factor = (fade_out_rem << 8) / total_fade_out; | ||
777 | |||
778 | fade_out_rem -= block_rem; | ||
779 | |||
780 | /* Fade this block */ | ||
781 | while (block_rem > 0 && fade_out_chunk != NULL) | ||
782 | { | ||
783 | /* Fade one sample */ | ||
784 | int16_t *buf = (int16_t *)fade_out_chunk->addr; | ||
785 | int32_t sample = buf[fade_out_sample]; | ||
786 | buf[fade_out_sample++] = (sample * factor) >> 8; | ||
787 | |||
788 | block_rem -= 2; | ||
789 | /* Move to the next chunk as needed */ | ||
790 | if (fade_out_sample * 2 >= fade_out_chunk->size) | ||
791 | { | ||
792 | fade_out_chunk = fade_out_chunk->link; | ||
793 | fade_out_sample = 0; | ||
794 | } | ||
795 | } | ||
796 | } | ||
797 | } | ||
798 | |||
799 | /* Initialize fade-in counters */ | ||
814 | crossfade_fade_in_total = | 800 | crossfade_fade_in_total = |
815 | NATIVE_FREQUENCY * global_settings.crossfade_fade_in_duration * 4; | 801 | NATIVE_FREQUENCY * global_settings.crossfade_fade_in_duration * 4; |
816 | crossfade_fade_in_rem = crossfade_fade_in_total; | 802 | crossfade_fade_in_rem = crossfade_fade_in_total; |
@@ -818,7 +804,10 @@ static void crossfade_start(void) | |||
818 | fade_in_delay = | 804 | fade_in_delay = |
819 | NATIVE_FREQUENCY * global_settings.crossfade_fade_in_delay * 4; | 805 | NATIVE_FREQUENCY * global_settings.crossfade_fade_in_delay * 4; |
820 | 806 | ||
821 | crossfade_process_buffer(fade_in_delay, fade_out_delay, fade_out_rem); | 807 | /* Find the right chunk and sample to start fading in */ |
808 | fade_in_delay += crossfade_sample * 2; | ||
809 | crossfade_sample = find_chunk(fade_in_delay, &crossfade_chunk); | ||
810 | logf("crossfade_start done!"); | ||
822 | } | 811 | } |
823 | 812 | ||
824 | /* Returns the number of bytes _NOT_ mixed */ | 813 | /* Returns the number of bytes _NOT_ mixed */ |