![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
test public
Dependencies: HttpServer_snapshot_mbed-os
PwmOutSpeaker.cpp
00001 /* mbed PwmOutSpeaker Library 00002 * Copyright (C) 2016 dkato 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "PwmOutSpeaker.h" 00018 00019 PwmOutSpeaker::PwmOutSpeaker(PinName pwm_l, PinName pwm_r) : 00020 _speaker_l(NULL), _speaker_r(NULL), _audioThread(osPriorityHigh), _sound_out_req(0) { 00021 _bottom = 0; 00022 _top = 0; 00023 _playing = false; 00024 if (pwm_l != NC) { 00025 _speaker_l = new PwmOut(pwm_l); 00026 } 00027 if (pwm_r != NC) { 00028 _speaker_r = new PwmOut(pwm_r); 00029 } 00030 _audioThread.start(callback(this, &PwmOutSpeaker::audio_process)); 00031 outputVolume(1.0f, 1.0f); 00032 format(16); 00033 frequency(44100); 00034 } 00035 00036 PwmOutSpeaker::~PwmOutSpeaker() { 00037 if (_speaker_l != NULL) { 00038 delete _speaker_l; 00039 } 00040 if (_speaker_r != NULL) { 00041 delete _speaker_r; 00042 } 00043 } 00044 00045 bool PwmOutSpeaker::format(char length) { 00046 switch (length) { 00047 case 8: 00048 case 16: 00049 break; 00050 default: 00051 return false; 00052 } 00053 _length = length; 00054 _data_cnt = 0; 00055 return true; 00056 } 00057 00058 bool PwmOutSpeaker::frequency(int hz) { 00059 int wk_us; 00060 00061 switch (hz) { 00062 case 48000: 00063 _hz_multi = 6; 00064 break; 00065 case 44100: 00066 _hz_multi = 5; 00067 break; 00068 case 32000: 00069 _hz_multi = 4; 00070 break; 00071 case 8021: 00072 case 8000: 00073 _hz_multi = 1; 00074 break; 00075 default: 00076 return false; 00077 } 00078 _playing = false; 00079 if (_speaker_l != NULL) { 00080 _speaker_l->write(0.5f); 00081 _speaker_l->period_us(10); // 100kHz 00082 } 00083 if (_speaker_r != NULL) { 00084 _speaker_r->write(0.5f); 00085 _speaker_r->period_us(10); // 100kHz 00086 } 00087 wk_us = (int)(1000000.0f / hz * _hz_multi + 0.5f); 00088 _timer.attach_us(Callback<void()>(this, &PwmOutSpeaker::sound_out), wk_us); 00089 _data_cnt = 0; 00090 00091 return true; 00092 } 00093 00094 int PwmOutSpeaker::write(void * const p_data, uint32_t data_size, const rbsp_data_conf_t * const p_data_conf) { 00095 int data_num; 00096 int i = 0; 00097 float wk_vol_l; 00098 float wk_ofs_l; 00099 float wk_vol_r; 00100 float wk_ofs_r; 00101 00102 if (_length == 8) { 00103 data_num = data_size; 00104 } else { 00105 data_num = data_size / 2; 00106 } 00107 while (i < data_num) { 00108 if (_data_cnt < (_hz_multi - 1)) { 00109 _data_cnt++; 00110 i += 2; 00111 } else { 00112 _data_cnt = 0; 00113 while (((_bottom + 2) & MSK_RING_BUFF) == _top) { 00114 ThisThread::sleep_for(1); 00115 } 00116 00117 wk_vol_l = _speaker_vol_l; 00118 wk_ofs_l = (1.0f - wk_vol_l) / 2; 00119 wk_vol_r = _speaker_vol_r; 00120 wk_ofs_r = (1.0f - wk_vol_r) / 2; 00121 if (_length == 8) { 00122 _pwm_duty_buf[_bottom] = ((float)((uint8_t *)p_data)[i++] / (float)0xff) * wk_vol_l + wk_ofs_l; 00123 _pwm_duty_buf[_bottom + 1] = ((float)((uint8_t *)p_data)[i++] / (float)0xff) * wk_vol_r + wk_ofs_r; 00124 } else { 00125 _pwm_duty_buf[_bottom] = ((float)(((int16_t *)p_data)[i++] + 0x8000) / (float)0xffff) * wk_vol_l + wk_ofs_l; 00126 _pwm_duty_buf[_bottom + 1] = ((float)(((int16_t *)p_data)[i++] + 0x8000) / (float)0xffff) * wk_vol_r + wk_ofs_r; 00127 } 00128 _bottom = (_bottom + 2) & MSK_RING_BUFF; 00129 } 00130 } 00131 00132 if (p_data_conf != NULL) { 00133 return data_size; 00134 } 00135 00136 if (p_data_conf->p_notify_func != NULL) { 00137 p_data_conf->p_notify_func(p_data, data_size, p_data_conf->p_app_data); 00138 } 00139 00140 return 0; 00141 } 00142 00143 bool PwmOutSpeaker::outputVolume(float leftVolumeOut, float rightVolumeOut) { 00144 if ((leftVolumeOut < 0.0) || (leftVolumeOut > 1.0)) { 00145 return false; 00146 } 00147 if ((rightVolumeOut < 0.0) || (rightVolumeOut > 1.0)) { 00148 return false; 00149 } 00150 _speaker_vol_l = leftVolumeOut; 00151 _speaker_vol_r = rightVolumeOut; 00152 return true; 00153 } 00154 00155 void PwmOutSpeaker::sound_out(void) { 00156 _sound_out_req.release(); 00157 } 00158 00159 void PwmOutSpeaker::audio_process() { 00160 while (true) { 00161 _sound_out_req.wait(); 00162 if (_top != _bottom) { 00163 if (_speaker_l != NULL) { 00164 _speaker_l->write(_pwm_duty_buf[_top + 0]); 00165 } 00166 if (_speaker_r != NULL) { 00167 _speaker_r->write(_pwm_duty_buf[_top + 1]); 00168 } 00169 _top = (_top + 2) & MSK_RING_BUFF; 00170 _playing = true; 00171 } else if (_playing) { 00172 if (_speaker_l != NULL) { 00173 _speaker_l->write(0.5f); 00174 } 00175 if (_speaker_r != NULL) { 00176 _speaker_r->write(0.5f); 00177 } 00178 _playing = false; 00179 } else { 00180 // do nothing 00181 } 00182 } 00183 } 00184
Generated on Wed Jul 13 2022 05:33:36 by
![doxygen](doxygen.png)