| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: audio.c,v 1.28.2.4 2019/11/19 12:58:29 martin Exp $ */ | | 1 | /* $NetBSD: audio.c,v 1.28.2.5 2020/01/02 09:18:15 martin Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Andrew Doran. | | 8 | * by Andrew Doran. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -132,27 +132,27 @@ | | | @@ -132,27 +132,27 @@ |
132 | * these may be also called after attach, the thread lock is required. | | 132 | * these may be also called after attach, the thread lock is required. |
133 | * | | 133 | * |
134 | * In addition, there is an additional lock. | | 134 | * In addition, there is an additional lock. |
135 | * | | 135 | * |
136 | * - track->lock. This is an atomic variable and is similar to the | | 136 | * - track->lock. This is an atomic variable and is similar to the |
137 | * "interrupt lock". This is one for each track. If any thread context | | 137 | * "interrupt lock". This is one for each track. If any thread context |
138 | * (and software interrupt context) and hardware interrupt context who | | 138 | * (and software interrupt context) and hardware interrupt context who |
139 | * want to access some variables on this track, they must acquire this | | 139 | * want to access some variables on this track, they must acquire this |
140 | * lock before. It protects track's consistency between hardware | | 140 | * lock before. It protects track's consistency between hardware |
141 | * interrupt context and others. | | 141 | * interrupt context and others. |
142 | */ | | 142 | */ |
143 | | | 143 | |
144 | #include <sys/cdefs.h> | | 144 | #include <sys/cdefs.h> |
145 | __KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.28.2.4 2019/11/19 12:58:29 martin Exp $"); | | 145 | __KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.28.2.5 2020/01/02 09:18:15 martin Exp $"); |
146 | | | 146 | |
147 | #ifdef _KERNEL_OPT | | 147 | #ifdef _KERNEL_OPT |
148 | #include "audio.h" | | 148 | #include "audio.h" |
149 | #include "midi.h" | | 149 | #include "midi.h" |
150 | #endif | | 150 | #endif |
151 | | | 151 | |
152 | #if NAUDIO > 0 | | 152 | #if NAUDIO > 0 |
153 | | | 153 | |
154 | #ifdef _KERNEL | | 154 | #ifdef _KERNEL |
155 | | | 155 | |
156 | #include <sys/types.h> | | 156 | #include <sys/types.h> |
157 | #include <sys/param.h> | | 157 | #include <sys/param.h> |
158 | #include <sys/atomic.h> | | 158 | #include <sys/atomic.h> |
| @@ -3051,61 +3051,51 @@ audioctl_open(dev_t dev, struct audio_so | | | @@ -3051,61 +3051,51 @@ audioctl_open(dev_t dev, struct audio_so |
3051 | af = kmem_zalloc(sizeof(audio_file_t), KM_SLEEP); | | 3051 | af = kmem_zalloc(sizeof(audio_file_t), KM_SLEEP); |
3052 | af->sc = sc; | | 3052 | af->sc = sc; |
3053 | af->dev = dev; | | 3053 | af->dev = dev; |
3054 | | | 3054 | |
3055 | /* Not necessary to insert sc_files. */ | | 3055 | /* Not necessary to insert sc_files. */ |
3056 | | | 3056 | |
3057 | error = fd_clone(fp, fd, flags, &audio_fileops, af); | | 3057 | error = fd_clone(fp, fd, flags, &audio_fileops, af); |
3058 | KASSERT(error == EMOVEFD); | | 3058 | KASSERT(error == EMOVEFD); |
3059 | | | 3059 | |
3060 | return error; | | 3060 | return error; |
3061 | } | | 3061 | } |
3062 | | | 3062 | |
3063 | /* | | 3063 | /* |
3064 | * Reallocate 'memblock' with specified 'bytes' if 'bytes' > 0. | | | |
3065 | * Or free 'memblock' and return NULL if 'byte' is zero. | | | |
3066 | */ | | | |
3067 | static void * | | | |
3068 | audio_realloc(void *memblock, size_t bytes) | | | |
3069 | { | | | |
3070 | | | | |
3071 | if (memblock != NULL) { | | | |
3072 | if (bytes != 0) { | | | |
3073 | return kern_realloc(memblock, bytes, M_NOWAIT); | | | |
3074 | } else { | | | |
3075 | kern_free(memblock); | | | |
3076 | return NULL; | | | |
3077 | } | | | |
3078 | } else { | | | |
3079 | if (bytes != 0) { | | | |
3080 | return kern_malloc(bytes, M_NOWAIT); | | | |
3081 | } else { | | | |
3082 | return NULL; | | | |
3083 | } | | | |
3084 | } | | | |
3085 | } | | | |
3086 | | | | |
3087 | /* | | | |
3088 | * Free 'mem' if available, and initialize the pointer. | | 3064 | * Free 'mem' if available, and initialize the pointer. |
3089 | * For this reason, this is implemented as macro. | | 3065 | * For this reason, this is implemented as macro. |
3090 | */ | | 3066 | */ |
3091 | #define audio_free(mem) do { \ | | 3067 | #define audio_free(mem) do { \ |
3092 | if (mem != NULL) { \ | | 3068 | if (mem != NULL) { \ |
3093 | kern_free(mem); \ | | 3069 | kern_free(mem); \ |
3094 | mem = NULL; \ | | 3070 | mem = NULL; \ |
3095 | } \ | | 3071 | } \ |
3096 | } while (0) | | 3072 | } while (0) |
3097 | | | 3073 | |
3098 | /* | | 3074 | /* |
| | | 3075 | * (Re)allocate 'memblock' with specified 'bytes'. |
| | | 3076 | * bytes must not be 0. |
| | | 3077 | * This function never returns NULL. |
| | | 3078 | */ |
| | | 3079 | static void * |
| | | 3080 | audio_realloc(void *memblock, size_t bytes) |
| | | 3081 | { |
| | | 3082 | |
| | | 3083 | KASSERT(bytes != 0); |
| | | 3084 | audio_free(memblock); |
| | | 3085 | return kern_malloc(bytes, M_WAITOK); |
| | | 3086 | } |
| | | 3087 | |
| | | 3088 | /* |
3099 | * (Re)allocate usrbuf with 'newbufsize' bytes. | | 3089 | * (Re)allocate usrbuf with 'newbufsize' bytes. |
3100 | * Use this function for usrbuf because only usrbuf can be mmapped. | | 3090 | * Use this function for usrbuf because only usrbuf can be mmapped. |
3101 | * If successful, it updates track->usrbuf.mem, track->usrbuf.capacity and | | 3091 | * If successful, it updates track->usrbuf.mem, track->usrbuf.capacity and |
3102 | * returns 0. Otherwise, it clears track->usrbuf.mem, track->usrbuf.capacity | | 3092 | * returns 0. Otherwise, it clears track->usrbuf.mem, track->usrbuf.capacity |
3103 | * and returns errno. | | 3093 | * and returns errno. |
3104 | * It must be called before updating usrbuf.capacity. | | 3094 | * It must be called before updating usrbuf.capacity. |
3105 | */ | | 3095 | */ |
3106 | static int | | 3096 | static int |
3107 | audio_realloc_usrbuf(audio_track_t *track, int newbufsize) | | 3097 | audio_realloc_usrbuf(audio_track_t *track, int newbufsize) |
3108 | { | | 3098 | { |
3109 | struct audio_softc *sc; | | 3099 | struct audio_softc *sc; |
3110 | vaddr_t vstart; | | 3100 | vaddr_t vstart; |
3111 | vsize_t oldvsize; | | 3101 | vsize_t oldvsize; |
| @@ -3650,38 +3640,36 @@ abort: | | | @@ -3650,38 +3640,36 @@ abort: |
3650 | #endif | | 3640 | #endif |
3651 | return NULL; | | 3641 | return NULL; |
3652 | } | | 3642 | } |
3653 | | | 3643 | |
3654 | /* | | 3644 | /* |
3655 | * Initialize the codec stage of this track as necessary. | | 3645 | * Initialize the codec stage of this track as necessary. |
3656 | * If successful, it initializes the codec stage as necessary, stores updated | | 3646 | * If successful, it initializes the codec stage as necessary, stores updated |
3657 | * last_dst in *last_dstp in any case, and returns 0. | | 3647 | * last_dst in *last_dstp in any case, and returns 0. |
3658 | * Otherwise, it returns errno without modifying *last_dstp. | | 3648 | * Otherwise, it returns errno without modifying *last_dstp. |
3659 | */ | | 3649 | */ |
3660 | static int | | 3650 | static int |
3661 | audio_track_init_codec(audio_track_t *track, audio_ring_t **last_dstp) | | 3651 | audio_track_init_codec(audio_track_t *track, audio_ring_t **last_dstp) |
3662 | { | | 3652 | { |
3663 | struct audio_softc *sc; | | | |
3664 | audio_ring_t *last_dst; | | 3653 | audio_ring_t *last_dst; |
3665 | audio_ring_t *srcbuf; | | 3654 | audio_ring_t *srcbuf; |
3666 | audio_format2_t *srcfmt; | | 3655 | audio_format2_t *srcfmt; |
3667 | audio_format2_t *dstfmt; | | 3656 | audio_format2_t *dstfmt; |
3668 | audio_filter_arg_t *arg; | | 3657 | audio_filter_arg_t *arg; |
3669 | u_int len; | | 3658 | u_int len; |
3670 | int error; | | 3659 | int error; |
3671 | | | 3660 | |
3672 | KASSERT(track); | | 3661 | KASSERT(track); |
3673 | | | 3662 | |
3674 | sc = track->mixer->sc; | | | |
3675 | last_dst = *last_dstp; | | 3663 | last_dst = *last_dstp; |
3676 | dstfmt = &last_dst->fmt; | | 3664 | dstfmt = &last_dst->fmt; |
3677 | srcfmt = &track->inputfmt; | | 3665 | srcfmt = &track->inputfmt; |
3678 | srcbuf = &track->codec.srcbuf; | | 3666 | srcbuf = &track->codec.srcbuf; |
3679 | error = 0; | | 3667 | error = 0; |
3680 | | | 3668 | |
3681 | if (srcfmt->encoding != dstfmt->encoding | | 3669 | if (srcfmt->encoding != dstfmt->encoding |
3682 | || srcfmt->precision != dstfmt->precision | | 3670 | || srcfmt->precision != dstfmt->precision |
3683 | || srcfmt->stride != dstfmt->stride) { | | 3671 | || srcfmt->stride != dstfmt->stride) { |
3684 | track->codec.dst = last_dst; | | 3672 | track->codec.dst = last_dst; |
3685 | | | 3673 | |
3686 | srcbuf->fmt = *dstfmt; | | 3674 | srcbuf->fmt = *dstfmt; |
3687 | srcbuf->fmt.encoding = srcfmt->encoding; | | 3675 | srcbuf->fmt.encoding = srcfmt->encoding; |
| @@ -3690,69 +3678,61 @@ audio_track_init_codec(audio_track_t *tr | | | @@ -3690,69 +3678,61 @@ audio_track_init_codec(audio_track_t *tr |
3690 | | | 3678 | |
3691 | track->codec.filter = audio_track_get_codec(track, | | 3679 | track->codec.filter = audio_track_get_codec(track, |
3692 | &srcbuf->fmt, dstfmt); | | 3680 | &srcbuf->fmt, dstfmt); |
3693 | if (track->codec.filter == NULL) { | | 3681 | if (track->codec.filter == NULL) { |
3694 | error = EINVAL; | | 3682 | error = EINVAL; |
3695 | goto abort; | | 3683 | goto abort; |
3696 | } | | 3684 | } |
3697 | | | 3685 | |
3698 | srcbuf->head = 0; | | 3686 | srcbuf->head = 0; |
3699 | srcbuf->used = 0; | | 3687 | srcbuf->used = 0; |
3700 | srcbuf->capacity = frame_per_block(track->mixer, &srcbuf->fmt); | | 3688 | srcbuf->capacity = frame_per_block(track->mixer, &srcbuf->fmt); |
3701 | len = auring_bytelen(srcbuf); | | 3689 | len = auring_bytelen(srcbuf); |
3702 | srcbuf->mem = audio_realloc(srcbuf->mem, len); | | 3690 | srcbuf->mem = audio_realloc(srcbuf->mem, len); |
3703 | if (srcbuf->mem == NULL) { | | | |
3704 | device_printf(sc->sc_dev, "%s: malloc(%d) failed\n", | | | |
3705 | __func__, len); | | | |
3706 | error = ENOMEM; | | | |
3707 | goto abort; | | | |
3708 | } | | | |
3709 | | | 3691 | |
3710 | arg = &track->codec.arg; | | 3692 | arg = &track->codec.arg; |
3711 | arg->srcfmt = &srcbuf->fmt; | | 3693 | arg->srcfmt = &srcbuf->fmt; |
3712 | arg->dstfmt = dstfmt; | | 3694 | arg->dstfmt = dstfmt; |
3713 | arg->context = NULL; | | 3695 | arg->context = NULL; |
3714 | | | 3696 | |
3715 | *last_dstp = srcbuf; | | 3697 | *last_dstp = srcbuf; |
3716 | return 0; | | 3698 | return 0; |
3717 | } | | 3699 | } |
3718 | | | 3700 | |
3719 | abort: | | 3701 | abort: |
3720 | track->codec.filter = NULL; | | 3702 | track->codec.filter = NULL; |
3721 | audio_free(srcbuf->mem); | | 3703 | audio_free(srcbuf->mem); |
3722 | return error; | | 3704 | return error; |
3723 | } | | 3705 | } |
3724 | | | 3706 | |
3725 | /* | | 3707 | /* |
3726 | * Initialize the chvol stage of this track as necessary. | | 3708 | * Initialize the chvol stage of this track as necessary. |
3727 | * If successful, it initializes the chvol stage as necessary, stores updated | | 3709 | * If successful, it initializes the chvol stage as necessary, stores updated |
3728 | * last_dst in *last_dstp in any case, and returns 0. | | 3710 | * last_dst in *last_dstp in any case, and returns 0. |
3729 | * Otherwise, it returns errno without modifying *last_dstp. | | 3711 | * Otherwise, it returns errno without modifying *last_dstp. |
3730 | */ | | 3712 | */ |
3731 | static int | | 3713 | static int |
3732 | audio_track_init_chvol(audio_track_t *track, audio_ring_t **last_dstp) | | 3714 | audio_track_init_chvol(audio_track_t *track, audio_ring_t **last_dstp) |
3733 | { | | 3715 | { |
3734 | struct audio_softc *sc; | | | |
3735 | audio_ring_t *last_dst; | | 3716 | audio_ring_t *last_dst; |
3736 | audio_ring_t *srcbuf; | | 3717 | audio_ring_t *srcbuf; |
3737 | audio_format2_t *srcfmt; | | 3718 | audio_format2_t *srcfmt; |
3738 | audio_format2_t *dstfmt; | | 3719 | audio_format2_t *dstfmt; |
3739 | audio_filter_arg_t *arg; | | 3720 | audio_filter_arg_t *arg; |
3740 | u_int len; | | 3721 | u_int len; |
3741 | int error; | | 3722 | int error; |
3742 | | | 3723 | |
3743 | KASSERT(track); | | 3724 | KASSERT(track); |
3744 | | | 3725 | |
3745 | sc = track->mixer->sc; | | | |
3746 | last_dst = *last_dstp; | | 3726 | last_dst = *last_dstp; |
3747 | dstfmt = &last_dst->fmt; | | 3727 | dstfmt = &last_dst->fmt; |
3748 | srcfmt = &track->inputfmt; | | 3728 | srcfmt = &track->inputfmt; |
3749 | srcbuf = &track->chvol.srcbuf; | | 3729 | srcbuf = &track->chvol.srcbuf; |
3750 | error = 0; | | 3730 | error = 0; |
3751 | | | 3731 | |
3752 | /* Check whether channel volume conversion is necessary. */ | | 3732 | /* Check whether channel volume conversion is necessary. */ |
3753 | bool use_chvol = false; | | 3733 | bool use_chvol = false; |
3754 | for (int ch = 0; ch < srcfmt->channels; ch++) { | | 3734 | for (int ch = 0; ch < srcfmt->channels; ch++) { |
3755 | if (track->ch_volume[ch] != 256) { | | 3735 | if (track->ch_volume[ch] != 256) { |
3756 | use_chvol = true; | | 3736 | use_chvol = true; |
3757 | break; | | 3737 | break; |
3758 | } | | 3738 | } |
| @@ -3760,71 +3740,62 @@ audio_track_init_chvol(audio_track_t *tr | | | @@ -3760,71 +3740,62 @@ audio_track_init_chvol(audio_track_t *tr |
3760 | | | 3740 | |
3761 | if (use_chvol == true) { | | 3741 | if (use_chvol == true) { |
3762 | track->chvol.dst = last_dst; | | 3742 | track->chvol.dst = last_dst; |
3763 | track->chvol.filter = audio_track_chvol; | | 3743 | track->chvol.filter = audio_track_chvol; |
3764 | | | 3744 | |
3765 | srcbuf->fmt = *dstfmt; | | 3745 | srcbuf->fmt = *dstfmt; |
3766 | /* no format conversion occurs */ | | 3746 | /* no format conversion occurs */ |
3767 | | | 3747 | |
3768 | srcbuf->head = 0; | | 3748 | srcbuf->head = 0; |
3769 | srcbuf->used = 0; | | 3749 | srcbuf->used = 0; |
3770 | srcbuf->capacity = frame_per_block(track->mixer, &srcbuf->fmt); | | 3750 | srcbuf->capacity = frame_per_block(track->mixer, &srcbuf->fmt); |
3771 | len = auring_bytelen(srcbuf); | | 3751 | len = auring_bytelen(srcbuf); |
3772 | srcbuf->mem = audio_realloc(srcbuf->mem, len); | | 3752 | srcbuf->mem = audio_realloc(srcbuf->mem, len); |
3773 | if (srcbuf->mem == NULL) { | | | |
3774 | device_printf(sc->sc_dev, "%s: malloc(%d) failed\n", | | | |
3775 | __func__, len); | | | |
3776 | error = ENOMEM; | | | |
3777 | goto abort; | | | |
3778 | } | | | |
3779 | | | 3753 | |
3780 | arg = &track->chvol.arg; | | 3754 | arg = &track->chvol.arg; |
3781 | arg->srcfmt = &srcbuf->fmt; | | 3755 | arg->srcfmt = &srcbuf->fmt; |
3782 | arg->dstfmt = dstfmt; | | 3756 | arg->dstfmt = dstfmt; |
3783 | arg->context = track->ch_volume; | | 3757 | arg->context = track->ch_volume; |
3784 | | | 3758 | |
3785 | *last_dstp = srcbuf; | | 3759 | *last_dstp = srcbuf; |
3786 | return 0; | | 3760 | return 0; |
3787 | } | | 3761 | } |
3788 | | | 3762 | |
3789 | abort: | | | |
3790 | track->chvol.filter = NULL; | | 3763 | track->chvol.filter = NULL; |
3791 | audio_free(srcbuf->mem); | | 3764 | audio_free(srcbuf->mem); |
3792 | return error; | | 3765 | return error; |
3793 | } | | 3766 | } |
3794 | | | 3767 | |
3795 | /* | | 3768 | /* |
3796 | * Initialize the chmix stage of this track as necessary. | | 3769 | * Initialize the chmix stage of this track as necessary. |
3797 | * If successful, it initializes the chmix stage as necessary, stores updated | | 3770 | * If successful, it initializes the chmix stage as necessary, stores updated |
3798 | * last_dst in *last_dstp in any case, and returns 0. | | 3771 | * last_dst in *last_dstp in any case, and returns 0. |
3799 | * Otherwise, it returns errno without modifying *last_dstp. | | 3772 | * Otherwise, it returns errno without modifying *last_dstp. |
3800 | */ | | 3773 | */ |
3801 | static int | | 3774 | static int |
3802 | audio_track_init_chmix(audio_track_t *track, audio_ring_t **last_dstp) | | 3775 | audio_track_init_chmix(audio_track_t *track, audio_ring_t **last_dstp) |
3803 | { | | 3776 | { |
3804 | struct audio_softc *sc; | | | |
3805 | audio_ring_t *last_dst; | | 3777 | audio_ring_t *last_dst; |
3806 | audio_ring_t *srcbuf; | | 3778 | audio_ring_t *srcbuf; |
3807 | audio_format2_t *srcfmt; | | 3779 | audio_format2_t *srcfmt; |
3808 | audio_format2_t *dstfmt; | | 3780 | audio_format2_t *dstfmt; |
3809 | audio_filter_arg_t *arg; | | 3781 | audio_filter_arg_t *arg; |
3810 | u_int srcch; | | 3782 | u_int srcch; |
3811 | u_int dstch; | | 3783 | u_int dstch; |
3812 | u_int len; | | 3784 | u_int len; |
3813 | int error; | | 3785 | int error; |
3814 | | | 3786 | |
3815 | KASSERT(track); | | 3787 | KASSERT(track); |
3816 | | | 3788 | |
3817 | sc = track->mixer->sc; | | | |
3818 | last_dst = *last_dstp; | | 3789 | last_dst = *last_dstp; |
3819 | dstfmt = &last_dst->fmt; | | 3790 | dstfmt = &last_dst->fmt; |
3820 | srcfmt = &track->inputfmt; | | 3791 | srcfmt = &track->inputfmt; |
3821 | srcbuf = &track->chmix.srcbuf; | | 3792 | srcbuf = &track->chmix.srcbuf; |
3822 | error = 0; | | 3793 | error = 0; |
3823 | | | 3794 | |
3824 | srcch = srcfmt->channels; | | 3795 | srcch = srcfmt->channels; |
3825 | dstch = dstfmt->channels; | | 3796 | dstch = dstfmt->channels; |
3826 | if (srcch != dstch) { | | 3797 | if (srcch != dstch) { |
3827 | track->chmix.dst = last_dst; | | 3798 | track->chmix.dst = last_dst; |
3828 | | | 3799 | |
3829 | if (srcch >= 2 && dstch == 1) { | | 3800 | if (srcch >= 2 && dstch == 1) { |
3830 | track->chmix.filter = audio_track_chmix_mixLR; | | 3801 | track->chmix.filter = audio_track_chmix_mixLR; |
| @@ -3835,73 +3806,64 @@ audio_track_init_chmix(audio_track_t *tr | | | @@ -3835,73 +3806,64 @@ audio_track_init_chmix(audio_track_t *tr |
3835 | } else { | | 3806 | } else { |
3836 | track->chmix.filter = audio_track_chmix_expand; | | 3807 | track->chmix.filter = audio_track_chmix_expand; |
3837 | } | | 3808 | } |
3838 | | | 3809 | |
3839 | srcbuf->fmt = *dstfmt; | | 3810 | srcbuf->fmt = *dstfmt; |
3840 | srcbuf->fmt.channels = srcch; | | 3811 | srcbuf->fmt.channels = srcch; |
3841 | | | 3812 | |
3842 | srcbuf->head = 0; | | 3813 | srcbuf->head = 0; |
3843 | srcbuf->used = 0; | | 3814 | srcbuf->used = 0; |
3844 | /* XXX The buffer size should be able to calculate. */ | | 3815 | /* XXX The buffer size should be able to calculate. */ |
3845 | srcbuf->capacity = frame_per_block(track->mixer, &srcbuf->fmt); | | 3816 | srcbuf->capacity = frame_per_block(track->mixer, &srcbuf->fmt); |
3846 | len = auring_bytelen(srcbuf); | | 3817 | len = auring_bytelen(srcbuf); |
3847 | srcbuf->mem = audio_realloc(srcbuf->mem, len); | | 3818 | srcbuf->mem = audio_realloc(srcbuf->mem, len); |
3848 | if (srcbuf->mem == NULL) { | | | |
3849 | device_printf(sc->sc_dev, "%s: malloc(%d) failed\n", | | | |
3850 | __func__, len); | | | |
3851 | error = ENOMEM; | | | |
3852 | goto abort; | | | |
3853 | } | | | |
3854 | | | 3819 | |
3855 | arg = &track->chmix.arg; | | 3820 | arg = &track->chmix.arg; |
3856 | arg->srcfmt = &srcbuf->fmt; | | 3821 | arg->srcfmt = &srcbuf->fmt; |
3857 | arg->dstfmt = dstfmt; | | 3822 | arg->dstfmt = dstfmt; |
3858 | arg->context = NULL; | | 3823 | arg->context = NULL; |
3859 | | | 3824 | |
3860 | *last_dstp = srcbuf; | | 3825 | *last_dstp = srcbuf; |
3861 | return 0; | | 3826 | return 0; |
3862 | } | | 3827 | } |
3863 | | | 3828 | |
3864 | abort: | | | |
3865 | track->chmix.filter = NULL; | | 3829 | track->chmix.filter = NULL; |
3866 | audio_free(srcbuf->mem); | | 3830 | audio_free(srcbuf->mem); |
3867 | return error; | | 3831 | return error; |
3868 | } | | 3832 | } |
3869 | | | 3833 | |
3870 | /* | | 3834 | /* |
3871 | * Initialize the freq stage of this track as necessary. | | 3835 | * Initialize the freq stage of this track as necessary. |
3872 | * If successful, it initializes the freq stage as necessary, stores updated | | 3836 | * If successful, it initializes the freq stage as necessary, stores updated |
3873 | * last_dst in *last_dstp in any case, and returns 0. | | 3837 | * last_dst in *last_dstp in any case, and returns 0. |
3874 | * Otherwise, it returns errno without modifying *last_dstp. | | 3838 | * Otherwise, it returns errno without modifying *last_dstp. |
3875 | */ | | 3839 | */ |
3876 | static int | | 3840 | static int |
3877 | audio_track_init_freq(audio_track_t *track, audio_ring_t **last_dstp) | | 3841 | audio_track_init_freq(audio_track_t *track, audio_ring_t **last_dstp) |
3878 | { | | 3842 | { |
3879 | struct audio_softc *sc; | | | |
3880 | audio_ring_t *last_dst; | | 3843 | audio_ring_t *last_dst; |
3881 | audio_ring_t *srcbuf; | | 3844 | audio_ring_t *srcbuf; |
3882 | audio_format2_t *srcfmt; | | 3845 | audio_format2_t *srcfmt; |
3883 | audio_format2_t *dstfmt; | | 3846 | audio_format2_t *dstfmt; |
3884 | audio_filter_arg_t *arg; | | 3847 | audio_filter_arg_t *arg; |
3885 | uint32_t srcfreq; | | 3848 | uint32_t srcfreq; |
3886 | uint32_t dstfreq; | | 3849 | uint32_t dstfreq; |
3887 | u_int dst_capacity; | | 3850 | u_int dst_capacity; |
3888 | u_int mod; | | 3851 | u_int mod; |
3889 | u_int len; | | 3852 | u_int len; |
3890 | int error; | | 3853 | int error; |
3891 | | | 3854 | |
3892 | KASSERT(track); | | 3855 | KASSERT(track); |
3893 | | | 3856 | |
3894 | sc = track->mixer->sc; | | | |
3895 | last_dst = *last_dstp; | | 3857 | last_dst = *last_dstp; |
3896 | dstfmt = &last_dst->fmt; | | 3858 | dstfmt = &last_dst->fmt; |
3897 | srcfmt = &track->inputfmt; | | 3859 | srcfmt = &track->inputfmt; |
3898 | srcbuf = &track->freq.srcbuf; | | 3860 | srcbuf = &track->freq.srcbuf; |
3899 | error = 0; | | 3861 | error = 0; |
3900 | | | 3862 | |
3901 | srcfreq = srcfmt->sample_rate; | | 3863 | srcfreq = srcfmt->sample_rate; |
3902 | dstfreq = dstfmt->sample_rate; | | 3864 | dstfreq = dstfmt->sample_rate; |
3903 | if (srcfreq != dstfreq) { | | 3865 | if (srcfreq != dstfreq) { |
3904 | track->freq.dst = last_dst; | | 3866 | track->freq.dst = last_dst; |
3905 | | | 3867 | |
3906 | memset(track->freq_prev, 0, sizeof(track->freq_prev)); | | 3868 | memset(track->freq_prev, 0, sizeof(track->freq_prev)); |
3907 | memset(track->freq_curr, 0, sizeof(track->freq_curr)); | | 3869 | memset(track->freq_curr, 0, sizeof(track->freq_curr)); |
| @@ -3920,43 +3882,36 @@ audio_track_init_freq(audio_track_t *tra | | | @@ -3920,43 +3882,36 @@ audio_track_init_freq(audio_track_t *tra |
3920 | } else { | | 3882 | } else { |
3921 | track->freq.filter = audio_track_freq_down; | | 3883 | track->freq.filter = audio_track_freq_down; |
3922 | track->freq_current = 0; | | 3884 | track->freq_current = 0; |
3923 | } | | 3885 | } |
3924 | | | 3886 | |
3925 | srcbuf->fmt = *dstfmt; | | 3887 | srcbuf->fmt = *dstfmt; |
3926 | srcbuf->fmt.sample_rate = srcfreq; | | 3888 | srcbuf->fmt.sample_rate = srcfreq; |
3927 | | | 3889 | |
3928 | srcbuf->head = 0; | | 3890 | srcbuf->head = 0; |
3929 | srcbuf->used = 0; | | 3891 | srcbuf->used = 0; |
3930 | srcbuf->capacity = frame_per_block(track->mixer, &srcbuf->fmt); | | 3892 | srcbuf->capacity = frame_per_block(track->mixer, &srcbuf->fmt); |
3931 | len = auring_bytelen(srcbuf); | | 3893 | len = auring_bytelen(srcbuf); |
3932 | srcbuf->mem = audio_realloc(srcbuf->mem, len); | | 3894 | srcbuf->mem = audio_realloc(srcbuf->mem, len); |
3933 | if (srcbuf->mem == NULL) { | | | |
3934 | device_printf(sc->sc_dev, "%s: malloc(%d) failed\n", | | | |
3935 | __func__, len); | | | |
3936 | error = ENOMEM; | | | |
3937 | goto abort; | | | |
3938 | } | | | |
3939 | | | 3895 | |
3940 | arg = &track->freq.arg; | | 3896 | arg = &track->freq.arg; |
3941 | arg->srcfmt = &srcbuf->fmt; | | 3897 | arg->srcfmt = &srcbuf->fmt; |
3942 | arg->dstfmt = dstfmt;/*&last_dst->fmt;*/ | | 3898 | arg->dstfmt = dstfmt;/*&last_dst->fmt;*/ |
3943 | arg->context = track; | | 3899 | arg->context = track; |
3944 | | | 3900 | |
3945 | *last_dstp = srcbuf; | | 3901 | *last_dstp = srcbuf; |
3946 | return 0; | | 3902 | return 0; |
3947 | } | | 3903 | } |
3948 | | | 3904 | |
3949 | abort: | | | |
3950 | track->freq.filter = NULL; | | 3905 | track->freq.filter = NULL; |
3951 | audio_free(srcbuf->mem); | | 3906 | audio_free(srcbuf->mem); |
3952 | return error; | | 3907 | return error; |
3953 | } | | 3908 | } |
3954 | | | 3909 | |
3955 | /* | | 3910 | /* |
3956 | * When playing back: (e.g. if codec and freq stage are valid) | | 3911 | * When playing back: (e.g. if codec and freq stage are valid) |
3957 | * | | 3912 | * |
3958 | * write | | 3913 | * write |
3959 | * | uiomove | | 3914 | * | uiomove |
3960 | * v | | 3915 | * v |
3961 | * usrbuf [...............] byte ring buffer (mmap-able) | | 3916 | * usrbuf [...............] byte ring buffer (mmap-able) |
3962 | * | memcpy | | 3917 | * | memcpy |
| @@ -4118,32 +4073,26 @@ audio_track_set_format(audio_track_t *tr | | | @@ -4118,32 +4073,26 @@ audio_track_set_format(audio_track_t *tr |
4118 | | | 4073 | |
4119 | /* Stage input buffer */ | | 4074 | /* Stage input buffer */ |
4120 | track->input = last_dst; | | 4075 | track->input = last_dst; |
4121 | | | 4076 | |
4122 | /* | | 4077 | /* |
4123 | * On the recording track, make the first stage a ring buffer. | | 4078 | * On the recording track, make the first stage a ring buffer. |
4124 | * XXX is there a better way? | | 4079 | * XXX is there a better way? |
4125 | */ | | 4080 | */ |
4126 | if (audio_track_is_record(track)) { | | 4081 | if (audio_track_is_record(track)) { |
4127 | track->input->capacity = NBLKOUT * | | 4082 | track->input->capacity = NBLKOUT * |
4128 | frame_per_block(track->mixer, &track->input->fmt); | | 4083 | frame_per_block(track->mixer, &track->input->fmt); |
4129 | len = auring_bytelen(track->input); | | 4084 | len = auring_bytelen(track->input); |
4130 | track->input->mem = audio_realloc(track->input->mem, len); | | 4085 | track->input->mem = audio_realloc(track->input->mem, len); |
4131 | if (track->input->mem == NULL) { | | | |
4132 | device_printf(sc->sc_dev, "malloc input(%d) failed\n", | | | |
4133 | len); | | | |
4134 | error = ENOMEM; | | | |
4135 | goto error; | | | |
4136 | } | | | |
4137 | } | | 4086 | } |
4138 | | | 4087 | |
4139 | /* | | 4088 | /* |
4140 | * Output buffer. | | 4089 | * Output buffer. |
4141 | * On the playback track, its capacity is NBLKOUT blocks. | | 4090 | * On the playback track, its capacity is NBLKOUT blocks. |
4142 | * On the recording track, its capacity is 1 block. | | 4091 | * On the recording track, its capacity is 1 block. |
4143 | */ | | 4092 | */ |
4144 | track->outbuf.head = 0; | | 4093 | track->outbuf.head = 0; |
4145 | track->outbuf.used = 0; | | 4094 | track->outbuf.used = 0; |
4146 | track->outbuf.capacity = frame_per_block(track->mixer, | | 4095 | track->outbuf.capacity = frame_per_block(track->mixer, |
4147 | &track->outbuf.fmt); | | 4096 | &track->outbuf.fmt); |
4148 | if (audio_track_is_playback(track)) | | 4097 | if (audio_track_is_playback(track)) |
4149 | track->outbuf.capacity *= NBLKOUT; | | 4098 | track->outbuf.capacity *= NBLKOUT; |
| @@ -4718,33 +4667,26 @@ audio_mixer_init(struct audio_softc *sc, | | | @@ -4718,33 +4667,26 @@ audio_mixer_init(struct audio_softc *sc, |
4718 | mixer->swap_endian = true; | | 4667 | mixer->swap_endian = true; |
4719 | TRACE(1, "swap_endian"); | | 4668 | TRACE(1, "swap_endian"); |
4720 | } | | 4669 | } |
4721 | | | 4670 | |
4722 | if (mode == AUMODE_PLAY) { | | 4671 | if (mode == AUMODE_PLAY) { |
4723 | /* Mixing buffer */ | | 4672 | /* Mixing buffer */ |
4724 | mixer->mixfmt = mixer->track_fmt; | | 4673 | mixer->mixfmt = mixer->track_fmt; |
4725 | mixer->mixfmt.precision *= 2; | | 4674 | mixer->mixfmt.precision *= 2; |
4726 | mixer->mixfmt.stride *= 2; | | 4675 | mixer->mixfmt.stride *= 2; |
4727 | /* XXX TODO: use some macros? */ | | 4676 | /* XXX TODO: use some macros? */ |
4728 | len = mixer->frames_per_block * mixer->mixfmt.channels * | | 4677 | len = mixer->frames_per_block * mixer->mixfmt.channels * |
4729 | mixer->mixfmt.stride / NBBY; | | 4678 | mixer->mixfmt.stride / NBBY; |
4730 | mixer->mixsample = audio_realloc(mixer->mixsample, len); | | 4679 | mixer->mixsample = audio_realloc(mixer->mixsample, len); |
4731 | if (mixer->mixsample == NULL) { | | | |
4732 | device_printf(sc->sc_dev, | | | |
4733 | "%s: malloc mixsample(%d) failed\n", | | | |
4734 | __func__, len); | | | |
4735 | error = ENOMEM; | | | |
4736 | goto abort; | | | |
4737 | } | | | |
4738 | } else { | | 4680 | } else { |
4739 | /* No mixing buffer for recording */ | | 4681 | /* No mixing buffer for recording */ |
4740 | } | | 4682 | } |
4741 | | | 4683 | |
4742 | if (reg->codec) { | | 4684 | if (reg->codec) { |
4743 | mixer->codec = reg->codec; | | 4685 | mixer->codec = reg->codec; |
4744 | mixer->codecarg.context = reg->context; | | 4686 | mixer->codecarg.context = reg->context; |
4745 | if (mode == AUMODE_PLAY) { | | 4687 | if (mode == AUMODE_PLAY) { |
4746 | mixer->codecarg.srcfmt = &mixer->track_fmt; | | 4688 | mixer->codecarg.srcfmt = &mixer->track_fmt; |
4747 | mixer->codecarg.dstfmt = &mixer->hwbuf.fmt; | | 4689 | mixer->codecarg.dstfmt = &mixer->hwbuf.fmt; |
4748 | } else { | | 4690 | } else { |
4749 | mixer->codecarg.srcfmt = &mixer->hwbuf.fmt; | | 4691 | mixer->codecarg.srcfmt = &mixer->hwbuf.fmt; |
4750 | mixer->codecarg.dstfmt = &mixer->track_fmt; | | 4692 | mixer->codecarg.dstfmt = &mixer->track_fmt; |