
test public
Dependencies: HttpServer_snapshot_mbed-os
mbed-gr-libs/components/AUDIO/PwmOutSpeaker/PwmOutSpeaker.cpp@0:e9fd5575b10e, 2019-10-18 (annotated)
- Committer:
- anhtran
- Date:
- Fri Oct 18 03:09:43 2019 +0000
- Revision:
- 0:e9fd5575b10e
abc
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
anhtran | 0:e9fd5575b10e | 1 | /* mbed PwmOutSpeaker Library |
anhtran | 0:e9fd5575b10e | 2 | * Copyright (C) 2016 dkato |
anhtran | 0:e9fd5575b10e | 3 | * |
anhtran | 0:e9fd5575b10e | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
anhtran | 0:e9fd5575b10e | 5 | * you may not use this file except in compliance with the License. |
anhtran | 0:e9fd5575b10e | 6 | * You may obtain a copy of the License at |
anhtran | 0:e9fd5575b10e | 7 | * |
anhtran | 0:e9fd5575b10e | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
anhtran | 0:e9fd5575b10e | 9 | * |
anhtran | 0:e9fd5575b10e | 10 | * Unless required by applicable law or agreed to in writing, software |
anhtran | 0:e9fd5575b10e | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
anhtran | 0:e9fd5575b10e | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
anhtran | 0:e9fd5575b10e | 13 | * See the License for the specific language governing permissions and |
anhtran | 0:e9fd5575b10e | 14 | * limitations under the License. |
anhtran | 0:e9fd5575b10e | 15 | */ |
anhtran | 0:e9fd5575b10e | 16 | |
anhtran | 0:e9fd5575b10e | 17 | #include "PwmOutSpeaker.h" |
anhtran | 0:e9fd5575b10e | 18 | |
anhtran | 0:e9fd5575b10e | 19 | PwmOutSpeaker::PwmOutSpeaker(PinName pwm_l, PinName pwm_r) : |
anhtran | 0:e9fd5575b10e | 20 | _speaker_l(NULL), _speaker_r(NULL), _audioThread(osPriorityHigh), _sound_out_req(0) { |
anhtran | 0:e9fd5575b10e | 21 | _bottom = 0; |
anhtran | 0:e9fd5575b10e | 22 | _top = 0; |
anhtran | 0:e9fd5575b10e | 23 | _playing = false; |
anhtran | 0:e9fd5575b10e | 24 | if (pwm_l != NC) { |
anhtran | 0:e9fd5575b10e | 25 | _speaker_l = new PwmOut(pwm_l); |
anhtran | 0:e9fd5575b10e | 26 | } |
anhtran | 0:e9fd5575b10e | 27 | if (pwm_r != NC) { |
anhtran | 0:e9fd5575b10e | 28 | _speaker_r = new PwmOut(pwm_r); |
anhtran | 0:e9fd5575b10e | 29 | } |
anhtran | 0:e9fd5575b10e | 30 | _audioThread.start(callback(this, &PwmOutSpeaker::audio_process)); |
anhtran | 0:e9fd5575b10e | 31 | outputVolume(1.0f, 1.0f); |
anhtran | 0:e9fd5575b10e | 32 | format(16); |
anhtran | 0:e9fd5575b10e | 33 | frequency(44100); |
anhtran | 0:e9fd5575b10e | 34 | } |
anhtran | 0:e9fd5575b10e | 35 | |
anhtran | 0:e9fd5575b10e | 36 | PwmOutSpeaker::~PwmOutSpeaker() { |
anhtran | 0:e9fd5575b10e | 37 | if (_speaker_l != NULL) { |
anhtran | 0:e9fd5575b10e | 38 | delete _speaker_l; |
anhtran | 0:e9fd5575b10e | 39 | } |
anhtran | 0:e9fd5575b10e | 40 | if (_speaker_r != NULL) { |
anhtran | 0:e9fd5575b10e | 41 | delete _speaker_r; |
anhtran | 0:e9fd5575b10e | 42 | } |
anhtran | 0:e9fd5575b10e | 43 | } |
anhtran | 0:e9fd5575b10e | 44 | |
anhtran | 0:e9fd5575b10e | 45 | bool PwmOutSpeaker::format(char length) { |
anhtran | 0:e9fd5575b10e | 46 | switch (length) { |
anhtran | 0:e9fd5575b10e | 47 | case 8: |
anhtran | 0:e9fd5575b10e | 48 | case 16: |
anhtran | 0:e9fd5575b10e | 49 | break; |
anhtran | 0:e9fd5575b10e | 50 | default: |
anhtran | 0:e9fd5575b10e | 51 | return false; |
anhtran | 0:e9fd5575b10e | 52 | } |
anhtran | 0:e9fd5575b10e | 53 | _length = length; |
anhtran | 0:e9fd5575b10e | 54 | _data_cnt = 0; |
anhtran | 0:e9fd5575b10e | 55 | return true; |
anhtran | 0:e9fd5575b10e | 56 | } |
anhtran | 0:e9fd5575b10e | 57 | |
anhtran | 0:e9fd5575b10e | 58 | bool PwmOutSpeaker::frequency(int hz) { |
anhtran | 0:e9fd5575b10e | 59 | int wk_us; |
anhtran | 0:e9fd5575b10e | 60 | |
anhtran | 0:e9fd5575b10e | 61 | switch (hz) { |
anhtran | 0:e9fd5575b10e | 62 | case 48000: |
anhtran | 0:e9fd5575b10e | 63 | _hz_multi = 6; |
anhtran | 0:e9fd5575b10e | 64 | break; |
anhtran | 0:e9fd5575b10e | 65 | case 44100: |
anhtran | 0:e9fd5575b10e | 66 | _hz_multi = 5; |
anhtran | 0:e9fd5575b10e | 67 | break; |
anhtran | 0:e9fd5575b10e | 68 | case 32000: |
anhtran | 0:e9fd5575b10e | 69 | _hz_multi = 4; |
anhtran | 0:e9fd5575b10e | 70 | break; |
anhtran | 0:e9fd5575b10e | 71 | case 8021: |
anhtran | 0:e9fd5575b10e | 72 | case 8000: |
anhtran | 0:e9fd5575b10e | 73 | _hz_multi = 1; |
anhtran | 0:e9fd5575b10e | 74 | break; |
anhtran | 0:e9fd5575b10e | 75 | default: |
anhtran | 0:e9fd5575b10e | 76 | return false; |
anhtran | 0:e9fd5575b10e | 77 | } |
anhtran | 0:e9fd5575b10e | 78 | _playing = false; |
anhtran | 0:e9fd5575b10e | 79 | if (_speaker_l != NULL) { |
anhtran | 0:e9fd5575b10e | 80 | _speaker_l->write(0.5f); |
anhtran | 0:e9fd5575b10e | 81 | _speaker_l->period_us(10); // 100kHz |
anhtran | 0:e9fd5575b10e | 82 | } |
anhtran | 0:e9fd5575b10e | 83 | if (_speaker_r != NULL) { |
anhtran | 0:e9fd5575b10e | 84 | _speaker_r->write(0.5f); |
anhtran | 0:e9fd5575b10e | 85 | _speaker_r->period_us(10); // 100kHz |
anhtran | 0:e9fd5575b10e | 86 | } |
anhtran | 0:e9fd5575b10e | 87 | wk_us = (int)(1000000.0f / hz * _hz_multi + 0.5f); |
anhtran | 0:e9fd5575b10e | 88 | _timer.attach_us(Callback<void()>(this, &PwmOutSpeaker::sound_out), wk_us); |
anhtran | 0:e9fd5575b10e | 89 | _data_cnt = 0; |
anhtran | 0:e9fd5575b10e | 90 | |
anhtran | 0:e9fd5575b10e | 91 | return true; |
anhtran | 0:e9fd5575b10e | 92 | } |
anhtran | 0:e9fd5575b10e | 93 | |
anhtran | 0:e9fd5575b10e | 94 | int PwmOutSpeaker::write(void * const p_data, uint32_t data_size, const rbsp_data_conf_t * const p_data_conf) { |
anhtran | 0:e9fd5575b10e | 95 | int data_num; |
anhtran | 0:e9fd5575b10e | 96 | int i = 0; |
anhtran | 0:e9fd5575b10e | 97 | float wk_vol_l; |
anhtran | 0:e9fd5575b10e | 98 | float wk_ofs_l; |
anhtran | 0:e9fd5575b10e | 99 | float wk_vol_r; |
anhtran | 0:e9fd5575b10e | 100 | float wk_ofs_r; |
anhtran | 0:e9fd5575b10e | 101 | |
anhtran | 0:e9fd5575b10e | 102 | if (_length == 8) { |
anhtran | 0:e9fd5575b10e | 103 | data_num = data_size; |
anhtran | 0:e9fd5575b10e | 104 | } else { |
anhtran | 0:e9fd5575b10e | 105 | data_num = data_size / 2; |
anhtran | 0:e9fd5575b10e | 106 | } |
anhtran | 0:e9fd5575b10e | 107 | while (i < data_num) { |
anhtran | 0:e9fd5575b10e | 108 | if (_data_cnt < (_hz_multi - 1)) { |
anhtran | 0:e9fd5575b10e | 109 | _data_cnt++; |
anhtran | 0:e9fd5575b10e | 110 | i += 2; |
anhtran | 0:e9fd5575b10e | 111 | } else { |
anhtran | 0:e9fd5575b10e | 112 | _data_cnt = 0; |
anhtran | 0:e9fd5575b10e | 113 | while (((_bottom + 2) & MSK_RING_BUFF) == _top) { |
anhtran | 0:e9fd5575b10e | 114 | ThisThread::sleep_for(1); |
anhtran | 0:e9fd5575b10e | 115 | } |
anhtran | 0:e9fd5575b10e | 116 | |
anhtran | 0:e9fd5575b10e | 117 | wk_vol_l = _speaker_vol_l; |
anhtran | 0:e9fd5575b10e | 118 | wk_ofs_l = (1.0f - wk_vol_l) / 2; |
anhtran | 0:e9fd5575b10e | 119 | wk_vol_r = _speaker_vol_r; |
anhtran | 0:e9fd5575b10e | 120 | wk_ofs_r = (1.0f - wk_vol_r) / 2; |
anhtran | 0:e9fd5575b10e | 121 | if (_length == 8) { |
anhtran | 0:e9fd5575b10e | 122 | _pwm_duty_buf[_bottom] = ((float)((uint8_t *)p_data)[i++] / (float)0xff) * wk_vol_l + wk_ofs_l; |
anhtran | 0:e9fd5575b10e | 123 | _pwm_duty_buf[_bottom + 1] = ((float)((uint8_t *)p_data)[i++] / (float)0xff) * wk_vol_r + wk_ofs_r; |
anhtran | 0:e9fd5575b10e | 124 | } else { |
anhtran | 0:e9fd5575b10e | 125 | _pwm_duty_buf[_bottom] = ((float)(((int16_t *)p_data)[i++] + 0x8000) / (float)0xffff) * wk_vol_l + wk_ofs_l; |
anhtran | 0:e9fd5575b10e | 126 | _pwm_duty_buf[_bottom + 1] = ((float)(((int16_t *)p_data)[i++] + 0x8000) / (float)0xffff) * wk_vol_r + wk_ofs_r; |
anhtran | 0:e9fd5575b10e | 127 | } |
anhtran | 0:e9fd5575b10e | 128 | _bottom = (_bottom + 2) & MSK_RING_BUFF; |
anhtran | 0:e9fd5575b10e | 129 | } |
anhtran | 0:e9fd5575b10e | 130 | } |
anhtran | 0:e9fd5575b10e | 131 | |
anhtran | 0:e9fd5575b10e | 132 | if (p_data_conf != NULL) { |
anhtran | 0:e9fd5575b10e | 133 | return data_size; |
anhtran | 0:e9fd5575b10e | 134 | } |
anhtran | 0:e9fd5575b10e | 135 | |
anhtran | 0:e9fd5575b10e | 136 | if (p_data_conf->p_notify_func != NULL) { |
anhtran | 0:e9fd5575b10e | 137 | p_data_conf->p_notify_func(p_data, data_size, p_data_conf->p_app_data); |
anhtran | 0:e9fd5575b10e | 138 | } |
anhtran | 0:e9fd5575b10e | 139 | |
anhtran | 0:e9fd5575b10e | 140 | return 0; |
anhtran | 0:e9fd5575b10e | 141 | } |
anhtran | 0:e9fd5575b10e | 142 | |
anhtran | 0:e9fd5575b10e | 143 | bool PwmOutSpeaker::outputVolume(float leftVolumeOut, float rightVolumeOut) { |
anhtran | 0:e9fd5575b10e | 144 | if ((leftVolumeOut < 0.0) || (leftVolumeOut > 1.0)) { |
anhtran | 0:e9fd5575b10e | 145 | return false; |
anhtran | 0:e9fd5575b10e | 146 | } |
anhtran | 0:e9fd5575b10e | 147 | if ((rightVolumeOut < 0.0) || (rightVolumeOut > 1.0)) { |
anhtran | 0:e9fd5575b10e | 148 | return false; |
anhtran | 0:e9fd5575b10e | 149 | } |
anhtran | 0:e9fd5575b10e | 150 | _speaker_vol_l = leftVolumeOut; |
anhtran | 0:e9fd5575b10e | 151 | _speaker_vol_r = rightVolumeOut; |
anhtran | 0:e9fd5575b10e | 152 | return true; |
anhtran | 0:e9fd5575b10e | 153 | } |
anhtran | 0:e9fd5575b10e | 154 | |
anhtran | 0:e9fd5575b10e | 155 | void PwmOutSpeaker::sound_out(void) { |
anhtran | 0:e9fd5575b10e | 156 | _sound_out_req.release(); |
anhtran | 0:e9fd5575b10e | 157 | } |
anhtran | 0:e9fd5575b10e | 158 | |
anhtran | 0:e9fd5575b10e | 159 | void PwmOutSpeaker::audio_process() { |
anhtran | 0:e9fd5575b10e | 160 | while (true) { |
anhtran | 0:e9fd5575b10e | 161 | _sound_out_req.wait(); |
anhtran | 0:e9fd5575b10e | 162 | if (_top != _bottom) { |
anhtran | 0:e9fd5575b10e | 163 | if (_speaker_l != NULL) { |
anhtran | 0:e9fd5575b10e | 164 | _speaker_l->write(_pwm_duty_buf[_top + 0]); |
anhtran | 0:e9fd5575b10e | 165 | } |
anhtran | 0:e9fd5575b10e | 166 | if (_speaker_r != NULL) { |
anhtran | 0:e9fd5575b10e | 167 | _speaker_r->write(_pwm_duty_buf[_top + 1]); |
anhtran | 0:e9fd5575b10e | 168 | } |
anhtran | 0:e9fd5575b10e | 169 | _top = (_top + 2) & MSK_RING_BUFF; |
anhtran | 0:e9fd5575b10e | 170 | _playing = true; |
anhtran | 0:e9fd5575b10e | 171 | } else if (_playing) { |
anhtran | 0:e9fd5575b10e | 172 | if (_speaker_l != NULL) { |
anhtran | 0:e9fd5575b10e | 173 | _speaker_l->write(0.5f); |
anhtran | 0:e9fd5575b10e | 174 | } |
anhtran | 0:e9fd5575b10e | 175 | if (_speaker_r != NULL) { |
anhtran | 0:e9fd5575b10e | 176 | _speaker_r->write(0.5f); |
anhtran | 0:e9fd5575b10e | 177 | } |
anhtran | 0:e9fd5575b10e | 178 | _playing = false; |
anhtran | 0:e9fd5575b10e | 179 | } else { |
anhtran | 0:e9fd5575b10e | 180 | // do nothing |
anhtran | 0:e9fd5575b10e | 181 | } |
anhtran | 0:e9fd5575b10e | 182 | } |
anhtran | 0:e9fd5575b10e | 183 | } |
anhtran | 0:e9fd5575b10e | 184 |