| 1 |
Adini_2012 |
Evidence-based support for the all-hazards approach to emergency preparedness |
Adini, Bruria; Goldberg, Avishay; Cohen, Robert; Laor, Daniel; Bar-Dayan, Yaron |
2012 |
2012-10-25 |
COMM-USE |
N |
PMC3494498 |
23098065.0 |
10.1186/2045-4015-1-40 |
mlp7m4m2 |
0.815387 |
Laurens_2019, Atkinson_2020, Amirov_2007 |
Hawryluck_2005 |
| 2 |
Marcozzi_2012 |
Measuring healthcare preparedness: an all-hazards approach |
Marcozzi, David E; Lurie, Nicole |
2012 |
2012-10-25 |
COMM-USE |
N |
PMC3502095 |
23098101.0 |
10.1186/2045-4015-1-42 |
rsnblu4d |
0.760089 |
Amirov_2007 |
Hawryluck_2005, Rebmann_2007, Adini_2012, Fausto_2020 |
| 3 |
Rebmann_2009 |
Assessing hospital emergency management plans: A guide for infection preventionists |
Rebmann, Terri |
2009 |
2009-11-30 |
PMC |
N |
PMC7132688 |
19699558.0 |
10.1016/j.ajic.2009.04.286 |
2a8kpr8y |
0.743794 |
Amirov_2007 |
Rebmann_2011, Rebmann_2009, Kudo_2018, Wang_2020 |
| 4 |
Price_2016 |
Chapter 11 Airport Emergency Planning, Part II Emergency Management Functions |
Price, Jeffrey C.; Forrest, Jeffrey S. |
2016 |
2016-12-31 |
PMC |
N |
PMC7170197 |
|
10.1016/b978-0-12-800515-6.00011-1 |
gt4h949p |
0.738376 |
Laurens_2019 |
Colling_2010, Fischer_2019, Seow_2013, Gui_L_2012 |
| 5 |
Stangeland_2010 |
Disaster Nursing: A Retrospective Review |
Stangeland, Paula A. |
2010 |
2010-12-31 |
PMC |
N |
PMC7135108 |
21095551.0 |
10.1016/j.ccell.2010.09.003 |
l765mxmy |
0.719355 |
|
Tzeng_2016, Achora_2016, Park_2017, Littleton-Kearney_2008 |
| 6 |
Paganini_2020 |
Translating COVID-19 Pandemic Surge Theory to Practice in the Emergency Department: How to Expand Structure |
Paganini, Matteo; Conti, Andrea; Weinstein, Eric; Della Corte, Francesco; Ragazzoni, Luca |
2020 |
2020-03-27 |
COMM-USE |
Y |
PMC7156581 |
32216865.0 |
10.1017/dmp.2020.57 |
ltk5hfc4 |
0.703179 |
Amirov_2007 |
|
| 7 |
Rebmann_2011 |
Assessing the infection prevention components of home health emergency management plans |
Rebmann, Terri; Citarella, Barbara; Subramaniam, Dipti P.; Subramaniam, Divya S. |
2011 |
2011-12-31 |
PMC |
N |
PMC7132649 |
21737179.0 |
10.1016/j.ajic.2011.02.008 |
kzlmeqyr |
0.679884 |
|
Rebmann_2009, Rebmann_2009 |
| 8 |
Fischer_2019 |
11 Contingency Planning Emergency Response and Safety |
Fischer, Robert J.; Halibozek, Edward P.; Walters, David C. |
2019 |
2019-12-31 |
PMC |
N |
PMC7149346 |
|
10.1016/b978-0-12-805310-2.00011-1 |
xqwkrktg |
0.678277 |
|
Seow_2013, Price_2016, Hawryluck_2005, Colling_2010 |
| 9 |
Dorasamy_2013 |
Knowledge management systems in support of disasters management: A two decade review |
Dorasamy, Magiswary; Raman, Murali; Kaliannan, Maniam |
2013 |
2013-11-30 |
PMC |
N |
PMC7111854 |
|
10.1016/j.techfore.2012.12.008 |
8bws4xpp |
0.666713 |
Amirov_2007 |
Hawryluck_2005, Seow_2013 |
| 10 |
Bennett_2018 |
Preparation for and organization during a major incident |
Bennett, Sean R. |
2018 |
2018-08-31 |
PMC |
N |
PMC7144093 |
|
10.1016/j.mpsur.2018.05.001 |
etnhpq9z |
0.648138 |
Amirov_2007, Atkinson_2020 |
Bennett_2015, Hawryluck_2005, Tzeng_2016, Kearns_2017 |
| 11 |
Colling_2010 |
Chapter 24 Emergency Preparedness—Planning and Management |
Colling, Russell L.; York, Tony W. |
2010 |
2010-12-31 |
PMC |
N |
PMC7152024 |
|
10.1016/b978-1-85617-613-2.00024-0 |
0p480zhb |
0.640650 |
Atkinson_2020 |
Hawryluck_2005, Price_2016, Seow_2013, Iserson_2008 |
| 12 |
Christian_2019 |
Triage |
Christian, Michael D. |
2019 |
2019-10-31 |
PMC |
N |
PMC7127292 |
31445606.0 |
10.1016/j.ccc.2019.06.009 |
gwle80we |
0.640262 |
Atkinson_2020, Amirov_2007 |
Hawryluck_2005, Kearns_2017, Aacharya_2011, Holt_2008 |
| 13 |
Burch_2009 |
Department of Homeland Security national planning scenarios: a spectrum of imaging findings to educate the radiologists |
Burch, Heather; Kitley, Charles A.; Naeem, Mohammed |
2009 |
2009-11-20 |
PMC |
N |
PMC7101611 |
19936809.0 |
10.1007/s10140-009-0849-z |
6ykfwmrr |
0.639381 |
|
Hawryluck_2005, Edwards_2007, Kearns_2017 |
| 14 |
Bennett_2015 |
Preparation for and organization during a major incident |
Bennett, Sean R. |
2015 |
2015-09-30 |
PMC |
N |
PMC7143673 |
|
10.1016/j.mpsur.2015.07.005 |
hz3oiywo |
0.638849 |
Atkinson_2020, Amirov_2007 |
Bennett_2018, Hawryluck_2005, Kearns_2017, Hick_2004 |
| 15 |
Devereaux_2014 |
Engagement and Education Care of the Critically Ill and Injured During Pandemics and Disasters: CHEST Consensus Statement |
Devereaux, Asha V.; Tosh, Pritish K.; Hick, John L.; Hanfling, Dan; Geiling, James; Reed, Mary Jane; Uyeki, Timothy M.; Shah, Umair A.; Fagbuyi, Daniel B.; Skippen, Peter; Dichter, Jeffrey R.; Kissoon, Niranjan; Christian, Michael D.; Upperman, Jeffrey S. |
2014 |
2014-10-31 |
None |
N |
PMC4504247 |
25144161.0 |
10.1378/chest.14-0740 |
t0r1jxm5 |
0.616613 |
Amirov_2007 |
King_2014, Tzeng_2016, Christian_2014 |
| 16 |
Rebmann_2009 |
APIC State-of-the-art Report: The role of the infection preventionist in emergency management |
Rebmann, Terri |
2009 |
2009-05-31 |
PMC |
N |
PMC7132651 |
19321230.0 |
10.1016/j.ajic.2008.12.002 |
k4qfi8zk |
0.613663 |
Laurens_2019, Atkinson_2020 |
Liu_Y_2020, Wang_2020 |
| 17 |
Nathawad_2013 |
Addressing the Gaps in Preparation for Quarantine |
Nathawad, Rita; Roblin, Patricia M.; Pruitt, Darrin; Arquilla, Bonnie |
2013 |
2013-01-28 |
PMC |
N |
PMC7113027 |
23356554.0 |
10.1017/s1049023x1200180x |
hdbbgee2 |
0.572765 |
|
|
| 18 |
Sprung_2010 |
Chapter 1. Introduction |
Sprung, Charles L.; Cohen, Robert; Adini, Bruria |
2010 |
2010-03-07 |
PMC |
N |
PMC7079978 |
19902176.0 |
10.1007/s00134-010-1760-5 |
cvuvsbwl |
0.569460 |
Laurens_2019, Amirov_2007 |
Wang_2020, Taylor_2010, Tzeng_2016, Rebmann_2009 |
| 19 |
King_2014 |
Evacuation of the ICU: Care of the Critically Ill and Injured During Pandemics and Disasters: CHEST Consensus Statement |
King, Mary A.; Niven, Alexander S.; Beninati, William; Fang, Ray; Einav, Sharon; Rubinson, Lewis; Kissoon, Niranjan; Devereaux, Asha V.; Christian, Michael D.; Grissom, Colin K. |
2014 |
2014-10-01 |
PMC |
N |
PMC4504249 |
25144509.0 |
10.1378/chest.14-0735 |
1pss52vl |
0.568130 |
Laurens_2019, Amirov_2007, Atkinson_2020 |
Rubinson_2008, Devereaux_2014, Christian_2014, Christian_2008 |
| 20 |
Kearns_2017 |
Disaster Preparedness and Response for the Burn Mass Casualty Incident in the Twenty-first Century |
Kearns, Randy D.; Marcozzi, David E.; Barry, Noran; Rubinson, Lewis; Hultman, Charles Scott; Rich, Preston B. |
2017 |
2017-07-31 |
PMC |
N |
PMC7112249 |
28576233.0 |
10.1016/j.cps.2017.02.004 |
t3iyrhx7 |
0.556961 |
Amirov_2007, Atkinson_2020, Laurens_2019, Mwabu_2008 |
Hawryluck_2005, Wax_R_2019, Edwards_2007, Rubinson_2008 |
| 21 |
Hon_K_2017 |
Review of Issues and Challenges of Practicing Emergency Medicine Above 30,000-Feet Altitude: 2 Anonymized Cases |
Hon, Kam Lun; Leung, Karen Ka Yan |
2017 |
2017-04-30 |
PMC |
N |
PMC7128818 |
28336016.0 |
10.1016/j.amj.2016.12.006 |
dz10xq98 |
0.550018 |
Atkinson_2020, Laurens_2019, Amirov_2007 |
Edwards_2007 |
| 22 |
Richards_2010 |
Chapter 9. Educational process |
Richards, Guy A.; Sprung, Charles L. |
2010 |
2010-03-07 |
PMC |
N |
PMC7080136 |
20213424.0 |
10.1007/s00134-010-1768-x |
6qz7bqnb |
0.550011 |
Amirov_2007 |
Tzeng_2016, Taylor_2010, Wang_2020 |
| 23 |
Marcino_2018 |
An overview of the National Microbiology Laboratory emergency management program |
Marcino, D; Gordon, K |
2018 |
2018-05-03 |
PMC |
N |
PMC6449121 |
31007619.0 |
10.14745/ccdr.v44i05a02 |
bst0guwr |
0.549499 |
|
Wang_2020, Liu_Y_2020 |
| 24 |
Lindgaard_2012 |
Chapter 7 Emergency Response in Simulated Terrorist Attacks Usability Lessons Learned |
Lindgaard, Gitte; Dudek, Cathy; Tsuji, Bruce; Noonan, Patrick; Sumegi, Livia; Stojmenovic, Milica |
2012 |
2012-12-31 |
PMC |
N |
PMC7149348 |
|
10.1016/b978-0-12-391063-9.00039-0 |
75dzc62b |
0.546607 |
Amirov_2007 |
Hawryluck_2005, Dorasamy_2013, Price_2016, Rebmann_2007 |
| 25 |
Roccaforte_2007 |
Disaster Preparedness, Triage, and Surge Capacity for Hospital Definitive Care Areas: Optimizing Outcomes when Demands Exceed Resources |
Roccaforte, J. David; Cushman, James G. |
2007 |
2007-03-31 |
PMC |
N |
|
17400163.0 |
10.1016/j.anclin.2007.01.002 |
307d2mtm |
0.537990 |
|
Orlando_2010, Wax_R_2019, Hawryluck_2005, Kearns_2017 |
| 26 |
Dara_2005 |
Engendering enthusiasm for sustainable disaster critical care response: why this is of consequence to critical care professionals? |
Dara, Saqib I; Ashton, Rendell W; Farmer, J Christopher |
2005 |
2005-01-27 |
PMC |
N |
PMC1175928 |
15774058.0 |
10.1186/cc3048 |
fooovon8 |
0.535893 |
Atkinson_2020, Amirov_2007 |
Hawryluck_2005, Rubinson_2008, Wax_R_2019, Kearns_2017 |
| 27 |
Prasad_2017 |
Natural Disasters |
Prasad, Abhaya S.; Francescutti, Louis Hugo |
2017 |
2017-12-31 |
PMC |
N |
|
|
10.1016/b978-0-12-803678-5.00519-1 |
9s15qwxo |
0.529428 |
Atkinson_2020 |
Argent_2009, Hawryluck_2005 |
| 28 |
Uhm_D_2019 |
Factors Affecting the Disaster Response Competency of Emergency Medical Technicians in South Korea |
Uhm, Dongchoon; Jung, Gyehyun; Yun, Yujin; Lee, Yongjae; Lim, Changuk |
2019 |
2019-10-31 |
PMC |
N |
PMC7104934 |
31589937.0 |
10.1016/j.anr.2019.09.005 |
bcatsh24 |
0.523875 |
|
Tzeng_2016, Liou_2020, Park_2017 |
| 29 |
Rebmann_2007 |
Disaster preparedness lessons learned and future directions for education: Results from focus groups conducted at the 2006 APIC Conference |
Rebmann, Terri; English, Judith F.; Carrico, Ruth |
2007 |
2007-08-31 |
PMC |
N |
PMC7132723 |
17660007.0 |
10.1016/j.ajic.2006.09.002 |
1eehtxin |
0.521662 |
Amirov_2007 |
Tzeng_2016, Uhm_D_2019 |
| 30 |
Marres_2011 |
Evaluation of admissions to the Major Incident Hospital based on a standardized protocol |
Marres, G. M. H.; van der Eijk, J.; Bemelman, M.; Leenen, L. P. H. |
2011 |
2011-02-03 |
NONCOMM |
N |
PMC3150834 |
21837255.0 |
10.1007/s00068-010-0067-0 |
9qjnhn8h |
0.510714 |
Amirov_2007 |
Hawryluck_2005, Tzeng_2016 |
| 31 |
Higgins_2004 |
Assessing hospital preparedness using an instrument based on the Mass Casualty Disaster Plan Checklist: Results of a statewide survey |
Higgins, Wayne; Wainright, Charles; Lu, Ning; Carrico, Ruth |
2004 |
2004-10-31 |
PMC |
N |
PMC7118834 |
15454888.0 |
10.1016/j.ajic.2004.03.006 |
mwlgvuag |
0.506107 |
|
Tzeng_2016, Hawryluck_2005, Vinson_2007, Shalhoub_2017 |
| 32 |
Liou_2020 |
Relationships between disaster nursing competence, anticipatory disaster stress and motivation for disaster engagement |
Liou, Shwu-Ru; Liu, Hsiu-Chen; Tsai, Hsiu-Min; Chu, Tsui-Ping; Cheng, Ching-Yu |
2020 |
2020-08-31 |
PMC |
N |
|
|
10.1016/j.ijdrr.2020.101545 |
4496gzdu |
0.502076 |
|
Tzeng_2016, Park_2017, Nukui_2018 |
| 33 |
Christian_2014 |
Introduction and Executive Summary Care of the Critically Ill and Injured During Pandemics and Disasters: CHEST Consensus Statement |
Christian, Michael D.; Devereaux, Asha V.; Dichter, Jeffrey R.; Rubinson, Lewis; Kissoon, Niranjan |
2014 |
2014-10-31 |
PMC |
N |
PMC7094437 |
25144202.0 |
10.1378/chest.14-0732 |
ul91jrpd |
0.491723 |
Amirov_2007 |
Hawryluck_2005, Rubinson_2008, King_2014, Christian_2008 |
| 34 |
Gui_L_2012 |
Prehospital Emergency Care in Shanghai: Present and Future |
Gui, Li; Gu, Shen; Lu, Feng; Zhou, Bin; Zhang, Ling |
2012 |
2012-12-31 |
PMC |
N |
PMC7126957 |
23047196.0 |
10.1016/j.jemermed.2012.02.067 |
zfhfgwsm |
0.488699 |
Laurens_2019 |
Edwards_2007, Liu_Y_2020, Huang_2020 |
| 35 |
Achora_2016 |
Disaster Preparedness: Need for inclusion in undergraduate nursing education |
Achora, Susan; Kamanyire, Joy K. |
2016 |
2016-02-02 |
PMC |
N |
PMC4746037 |
26909207.0 |
10.18295/squmj.2<IP_ADDRESS> |
opmkvllj |
0.482323 |
|
Littleton-Kearney_2008, Tzeng_2016, Park_2017, Ireland_2006 |
| 36 |
Wax_R_2019 |
Preparing the Intensive Care Unit for Disaster |
Wax, Randy S. |
2019 |
2019-10-31 |
PMC |
N |
PMC7127124 |
31445604.0 |
10.1016/j.ccc.2019.06.008 |
otr38534 |
0.482323 |
Amirov_2007, Atkinson_2020 |
Rubinson_2008, Hawryluck_2005, Orlando_2010, Kearns_2017 |
| 37 |
Johnson_2020 |
Response of chiropractic organizations to the COVID-19 pandemic: A descriptive report |
Johnson, Claire D.; Little, Craig S.; Sterling, Tamara A.; Gojkovich, Scott; Boghosian, Karlos; Ciolfi, Michael A. |
2020 |
2020-04-20 |
PMC |
Y |
|
|
10.1016/j.jmpt.2020.04.001 |
v0fdlt82 |
0.472627 |
|
|
| 38 |
Moser_2006 |
Development of a State Medical Surge Plan, Part II: Components of a Medical Surge Plan |
Moser, Royce; Connelly, Colleen; Baker, Lloyd; Barton, Richard; Buttrey, Jan; Morris, Stephen; Saffle, Jeffrey; Whitney, Jolene R. |
2006 |
2006-03-31 |
PMC |
N |
PMC7110659 |
16360636.0 |
10.1016/j.dmr.2005.11.001 |
9chbrfqj |
0.468070 |
|
Hick_2004, Rebmann_2007, Fausto_2020 |
| 39 |
Yoo_K_2019 |
Disaster preparedness for earthquakes in hemodialysis units in Gyeongju and Pohang, South Korea |
Yoo, Kyung Don; Kim, Hyo Jin; Kim, Yunmi; Park, Jae Yoon; Shin, Sung Joon; Han, Seung Hyeok; Kim, Dong Ki; Lim, Chun Soo; Kim, Yon Su |
2019 |
2019-02-18 |
NONCOMM |
N |
PMC6481979 |
30776874.0 |
10.23876/j.krcp.18.0058 |
71mbwaym |
0.466252 |
Atkinson_2020, Amirov_2007 |
Hawryluck_2005, Shalhoub_2017 |
| 40 |
Moran_2008 |
Biological Terrorism |
Moran, Gregory J.; Talan, David A.; Abrahamian, Fredrick M. |
2008 |
2008-03-31 |
PMC |
N |
PMC7126662 |
18295687.0 |
10.1016/j.idc.2007.12.003 |
pu0eputl |
0.435377 |
Atkinson_2020, Amirov_2007 |
Hawryluck_2005, Vinson_2007 |
| 41 |
Littleton-Kearney_2008 |
Directions for Disaster Nursing Education in the United States |
Littleton-Kearney, Marguerite T.; Slepski, Lynn A. |
2008 |
2008-03-31 |
PMC |
N |
PMC7134936 |
18206590.0 |
10.1016/j.ccell.2007.10.008 |
0tpdjdd2 |
0.434852 |
Amirov_2007 |
Achora_2016, Ireland_2006, Tzeng_2016 |
| 42 |
Liu_Y_2020 |
Emergency management of nursing human resources and supplies to respond to coronavirus disease 2019 epidemic |
Liu, Yu; Wang, Hui; Chen, Junhua; Zhang, Xiaoyun; Yue, Xiao; Ke, Jian; Wang, Binghua; Peng, Chaohua |
2020 |
2020-04-04 |
PMC |
Y |
|
|
10.1016/j.ijnss.2020.03.011 |
slejus63 |
0.415956 |
Amirov_2007, Laurens_2019 |
Wang_2020, Tzeng_2016 |
| 43 |
Taylor_2010 |
Chapter 6. Protection of patients and staff during a pandemic |
Taylor, Bruce L.; Montgomery, Hugh E.; Rhodes, Andrew; Sprung, Charles L. |
2010 |
2010-03-07 |
PMC |
N |
PMC7080106 |
20213421.0 |
10.1007/s00134-010-1764-1 |
a2he6tpj |
0.413376 |
Amirov_2007, Atkinson_2020 |
Wang_2020, Rebmann_2007, Tzeng_2016 |
| 44 |
Donner_2017 |
Is There a Doctor Onboard? Medical Emergencies at 40,000 Feet |
Donner, Howard J. |
2017 |
2017-05-31 |
PMC |
N |
PMC7125952 |
28411936.0 |
10.1016/j.emc.2017.01.005 |
qcaiijra |
0.404652 |
Atkinson_2020 |
Edwards_2007, Hon_K_2017 |
| 45 |
Hoard_2005 |
Systems modeling in support of evidence-based disaster planning for rural areas |
Hoard, Marna; Homer, Jack; Manley, William; Furbee, Paul; Haque, Arshadul; Helmkamp, James |
2005 |
2005-04-08 |
PMC |
N |
|
15881985.0 |
10.1016/j.ijheh.2005.01.011 |
ij3faz52 |
0.402572 |
Amirov_2007 |
Hawryluck_2005 |
| 46 |
Holt_2008 |
Making difficult ethical decisions in patient care during natural disasters and other mass casualty events |
Holt, G. Richard |
2008 |
2008-08-31 |
PMC |
N |
PMC7132512 |
18656712.0 |
10.1016/j.otohns.2008.04.027 |
6vf3km5i |
0.395851 |
|
Hawryluck_2005, Iserson_2008 |
| 47 |
Fong_2010 |
Litigation in Infections of Obstetrics and Gynecology |
Fong, I. W. |
2010 |
2010-11-30 |
PMC |
N |
PMC7119939 |
|
10.1007/978-1-4419-8053-3_4 |
8tsbsoxr |
0.379427 |
Laurens_2019, Atkinson_2020 |
|
| 48 |
Hang_2016 |
Experience in managing an urban massive burn incident: The Hangzhou bus attack on 5 July 2014 |
Hang, Hu; Jianan, Wang; Chunmao, Han |
2016 |
2016-02-29 |
PMC |
N |
PMC7117044 |
26526377.0 |
10.1016/j.burns.2015.09.015 |
g6d0kmr4 |
0.376815 |
Laurens_2019, Atkinson_2020, Oommen_2016, Naga_2015, Lohr_2018 |
Shalhoub_2017, Hawryluck_2005, Edwards_2007 |
| 49 |
Christian_2013 |
Biowarfare and Bioterrorism |
Christian, Michael D. |
2013 |
2013-07-31 |
PMC |
N |
PMC7127345 |
23830660.0 |
10.1016/j.ccc.2013.03.015 |
3dwqqgv1 |
0.369198 |
Atkinson_2020 |
|
| 50 |
Christian_2008 |
Definitive Care for the Critically Ill During a Disaster: Current Capabilities and Limitations From a Task Force for Mass Critical Care Summit Meeting, January 26–27, 2007, Chicago, IL |
Christian, Michael D.; Devereaux, Asha V.; Dichter, Jeffrey R.; Geiling, James A.; Rubinson, Lewis |
2008 |
2008-05-31 |
PMC |
N |
PMC7094433 |
18460503.0 |
10.1378/chest.07-2707 |
m8i3q9ww |
0.362546 |
Atkinson_2020, Amirov_2007 |
Rubinson_2008, Rubinson_2008, Hawryluck_2005, Edwards_2007 |
| 51 |
Orlando_2010 |
Perinatal Considerations in the Hospital Disaster Management Process |
Orlando, Susan; Danna, Denise; Giarratano, Gloria; Prepas, Robbie; Johnson, Cheri Barker |
2010 |
2010-08-31 |
PMC |
N |
PMC7126579 |
20629934.0 |
10.1111/j.1552-6909.2010.01158.x |
4wuxlb2w |
0.360936 |
Atkinson_2020, Amirov_2007 |
Tzeng_2016, Wax_R_2019, Wang_2020, Achora_2016 |
| 52 |
Hick_2004 |
Health care facility and community strategies for patient care surge capacity |
Hick, John L.; Hanfling, Dan; Burstein, Jonathan L.; DeAtley, Craig; Barbisch, Donna; Bogdan, Gregory M.; Cantrill, Stephen |
2004 |
2004-09-30 |
PMC |
N |
PMC7118880 |
15332068.0 |
10.1016/j.annemergmed.2004.04.011 |
6abs647e |
0.345899 |
|
Rebmann_2007, Hawryluck_2005, Rubinson_2008, Edwards_2007 |
| 53 |
Colling_2012 |
Chapter 42 Emergency Preparedness — Planning and Management* * Originally from Colling R, York TW. Hospital and healthcare security. Boston, MA: Butterworth-Heinemann; 2010. Updated by the editor, Elsevier, 2011. |
Colling, Russell; York, Tony W. |
2012 |
2012-12-31 |
PMC |
N |
PMC7148606 |
|
10.1016/b978-0-12-385246-5.00042-0 |
catxtvrm |
0.328727 |
Amirov_2007 |
Colling_2010, Kearns_2017, Hawryluck_2005, Wang_2020 |
| 54 |
Zhong_2014 |
Disaster resilience in tertiary hospitals: a cross-sectional survey in Shandong Province, China |
Zhong, Shuang; Hou, Xiang-Yu; Clark, Michele; Zang, Yu-Li; Wang, Lu; Xu, Ling-Zhong; FitzGerald, Gerard |
2014 |
2014-03-25 |
COMM-USE |
N |
PMC3987831 |
24661641.0 |
10.1186/1472-6963-14-135 |
idgtpokh |
0.325575 |
Laurens_2019, Atkinson_2020 |
Tzeng_2016 |
| 55 |
Kim_J_2004 |
Acute care issues in internationally adopted children |
Kim, Julia; Staat, Mary Allen |
2004 |
2004-06-30 |
PMC |
N |
PMC7129062 |
|
10.1016/j.cpem.2004.01.005 |
chcbiott |
0.325110 |
Atkinson_2020 |
|
| 56 |
Finegan_2020 |
International Committee of the Red Cross (ICRC): General guidance for the management of the dead related to COVID-19 |
Finegan, Oran; Fonseca, Stephen; Guyomarc’h, Pierre; Morcillo Mendez, Maria Dolores; Rodriguez Gonzalez, Jacqueline; Tidball-Binz, Morris; Winter, Kristy A. |
2020 |
2020-12-31 |
PMC |
Y |
|
|
10.1016/j.fsisyn.2020.03.007 |
rtybezro |
0.324054 |
|
Morton_2015 |
| 57 |
Sprung_2010 |
Recommendations for intensive care unit and hospital preparations for an influenza epidemic or mass disaster: summary report of the European Society of Intensive Care Medicine’s Task Force for intensive care unit triage during an influenza epidemic or mass disaster |
Sprung, Charles L.; Zimmerman, Janice L.; Christian, Michael D.; Joynt, Gavin M.; Hick, John L.; Taylor, Bruce; Richards, Guy A.; Sandrock, Christian; Cohen, Robert; Adini, Bruria |
2010 |
2010-02-05 |
PMC |
N |
PMC7079971 |
20135090.0 |
10.1007/s00134-010-1759-y |
g1gkhxwh |
0.314437 |
Amirov_2007, Laurens_2019 |
Rubinson_2008, Rubinson_2008, Rebmann_2007, Hawryluck_2005 |
| 58 |
Dara_2009 |
Preparedness Lessons from Modern Disasters and Wars |
Dara, Saqib I.; Farmer, J. Christopher |
2009 |
2009-01-31 |
PMC |
N |
PMC7126643 |
19268794.0 |
10.1016/j.ccc.2008.10.005 |
9aycb9cg |
0.301844 |
Amirov_2007 |
Hawryluck_2005, Kearns_2017 |


Korporatiewe Bank FNBSA Limited / Beperk trading / handeldrywend as FNBSA Corporate Bank/FNBSA Corporatiewe Bank Director Audit / Accounts Units, Foreign Remittance Department ATTN:Sir/Madam, Good day! My name is MRS, GLORIA ZUMA, the Director in charge of Audit /Accounts Unit, Foreign Remittance Department of FIRST NATIONAL BANK SOTH AFRICA,. Your contact is be courtesy of Johannesburg Chamber of Commerce and Industry. During auditing, verification/investigation in out bank at the end of last fiscal (financial) year, I discovered the sum of US$<IP_ADDRESS>(FIFTHEEN MILLION UNITED STATES DOLLARS) in a dormant account belonging to an Israeli International businessman who died along with his family in a plane crash on 5th November, 1997 in Abidjan, Cote D�Ivoire. My investigations revealed no survival for claims as I have long been expecting someone to forward applications for claims as it applies to our bankingregulations and if I do not remit this money out urgently, it will be forfeited. However, I kept this information (SECRET) confidential within my jurisdiction to enable me submit claims and transfer this fund through trustworthy person whom I shall present as the bonafide next of kin to the deceased. With my position now in the office, I can transfer this fund to any reliable designated foreign account, with assurance that this fund will be intact pending my physical arrival in your country for sharing. All documents to this transfer will be destroyed on confirmation of the money in your account thus leaving no trace to anything. Meanwhile, all domestic arrangements have been put in place awaiting your response to enable me conclude this transaction. At the conclusion of this transaction, you will be given 40% Of United States Dollars of the total amount, 60% of United States Dollars of the total amount will be for me and Investment in your country.I need your strong assurance and confidentiality. God bless us. Best regards. Mr. MRS GLORIA ZUMA, Alternative email:gloria_zuma_son@myway.com


init_package(pn)
Load and link the core.sn file of the package named pn. Return the name of the file that contain the machine code of core.sn.
core.sn
pn
Core Module Index | Contents


Hangman
[ Press any key to start!


EFA enquiries
Contact form https://form.education...
For all enquiries for the Education Funding Agency
Guidance
Information about the Academies Capital Maintenance Fund (ACMF).
The Academies Capital Maintenance Fund is now closed and has been replaced by the Condition Improvement Fund .
EFA has also published a series of property information notes (PINs) to help academy trusts that are seeking consent for property transactions.
In total 2,015 academies applied for 3,300 projects worth more than £1.4 billion.
Following assessment and moderation £393 million has been allocated to 1,134 academies for 1,388 projects .
In total 192 academies applied for projects requesting £33 million.
101 academies were successful, receiving a total allocation of almost £16 million.
You can view information on past funding allocations in the document ‘academies capital maintenance fund: historical data’ .
Contact form https://form.education...
For all enquiries for the Education Funding Agency
Published: 11 March 2014
Updated: 29 May 2014


Let's play!
Rules:
Ping Pong will count up to the number from 1 with the following exceptions:
- Numbers divisible by 3 become "ping"
- Numbers divisible by 5 become "ping"
- Numbers divisible by 15 become "ping-pong"
Dan Nollette
Dan-Nollette
This page was created as part of my course of study at Epicodus. It mimics a page credited to Kit Fisto.
Ping Pong will count up to the number from 1 with the following exceptions:


Title
Minimum
Maximum
Gauge Color
Needle Color
Scale font
Sample #1
Sample #2
Default
Allow interaction
Major Ticks interval
Major Ticks length
Major Ticks Color
Minor Ticks interval
Minor Ticks length
Minor Ticks Color


RealSense Calibrator - performing your first calibration
Prerequisite: Setting up for calibration
It is strongly recommended that you read this document in its entirety before starting.
The whole process will take about 30 minutes.
-
Good, even lighting is essential.
-
Fire up RealSenseCalibrator\bin\x64\Release\UI.exe.
Hover the mouse over the interface elements to see the tooltips. Do not change any settings.
-
Place the camera at the zero mark, and line it up to the blue centre crosshair so that the camera is pointing
exactly along the line of markers:
-
Centre your plane of targets on the 1-metre mark, facing back to the camera.
Measure the distance from the front glass of the camera to
the centre of the target with a ruler. Move the camera until the glass is exactly 1 metre away from the target.
The camera's position and orientation is now established, 1 metre from from the target, perfectly perpendicular and
aligned with your markers line on the floor.
-
Move the plane towards the camera until the edges of the green
circles are close to the edges of the image:
Move the plane such that the blue crosshairs interesct all the red targets.
-
Measure the distance from the camera's front glass to the centre of the target. This will probably be around
600mm. Enter this value, in mm, in the Range field:
-
The vertical distance between the centres of the 2 left red targets is the HEIGHT in mm.
The distance between the centres of the 2 right red targets must be the same.
The horizontal distance between the centres of the 2 top red targets is the WIDTH in mm.
The distance between the centres of the 2 bottom red targets must be the same.
Enter these mm values in the width and height fields:
-
Click "Find Targets". Wait a moment for the all the red pixels to be identified. At first, the plane will probably not be perfectly perpendicular to the camera.
In this case the target display will indicate how the plane needs to be adjusted, with "Too close" and "Too far" in blue:
Here, the top of the target is tilted towards the camera and the target is rotated clockwise looking from the top.
The actual misalignment can be observed by comparing the range fields left/right and top/bottom.
-
When you reposition the plane to improve the alignment, the targets will distort:
This is normal, click "Find Targets" to restart the alignment.
Wait a few moments for the red circles to be correctly identified again before making further adjustments.
The program considers the alignment satisfactory when the difference is less than 0.3% of the range.
Don't worry if you can't get it perfectly perpendicular, the program compensates for minor errors.
-
Click "Measure". The counters reset, the frame rate increases and the ranges start recording:
-
The MeanRange will slowly converge. When it seems well settled (only changing be hundredths of a mm, usually after a minute or two),
click "Finalise".
-
Click "Optimise". The optimiser displays its progress in the window at the bottom.
The results will not be very accurate but they should already be a significant improvement on
the values calculated using the camera's intrinsics (here, nearly a factor of 4 better):
Notice the warning in the lower window: As only one plane has been measured, there is not enough data
to calculate the camera's non-linearity.
-
Move the plane away from the camera to the 1-metre mark. Enter the range value, 1'000. Go to step 5.
-
Repeat for 1m50, 2m and 2m50. At longer distances, it may take a while to identify all the red pixels and the result
might not be a nice circle. It's not important.
-
Click "Optimise" again. The warning about quadratic terms should not appear:
-
Click "Chart" to display a comparison between the error using the camera's intrinsics and the error
using the optimised values:
-
Click "File->Save" and choose a folder. Two CSV files and an XML file will be created:
"435 xxxxxx Planes.csv" and "435 xxxxxx Trinsics.csv" and "435 xxxxxx.xml" where
xxxxxx is the serial number of the camera. These are discussed in the next section.
Up: Home
Previous: Setting up for calibration
Next: Analysing the results


I'm really sorry, but ::app:: encountered some kind of... well... a bug.
The best thing to do would be to send me the followind informations by filling an "issue" on GitHub (see below), so I can fix the problem.


Socket.io, RxJS example
Resource
Find
Find all
Subscribtions
Value:
Nothing yet...
Subscribe
Unubscribe
Chat
Send


/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA
*/
#include "conv.h"
#include "fluid.h"
#include "sfont.h"
#include "gen.h"
#include "voice.h"
namespace FluidS {
#define FLUID_SAMPLESANITY_CHECK (1 << 0)
#define FLUID_SAMPLESANITY_STARTUP (1 << 1)
#define fluid_clip(_val, _min, _max) \
{ (_val) = ((_val) < (_min))? (_min) : (((_val) > (_max))? (_max) : (_val)); }
/* used for filter turn off optimization - if filter cutoff is above the
specified value and filter q is below the other value, turn filter off */
#define FLUID_MAX_AUDIBLE_FILTER_FC 19000.0f
#define FLUID_MIN_AUDIBLE_FILTER_Q 1.2f
/* Smallest amplitude that can be perceived (full scale is +/- 0.5)
* 16 bits => 96+4=100 dB dynamic range => 0.00001
* 0.00001 * 2 is approximately 0.00003 :)
*/
#define FLUID_NOISE_FLOOR 0.00003f
/* these should be the absolute minimum that FluidSynth can deal with */
#define FLUID_MIN_LOOP_SIZE 2
#define FLUID_MIN_LOOP_PAD 0
/* min vol envelope release (to stop clicks) in SoundFont timecents */
#define FLUID_MIN_VOLENVRELEASE -7200.0f /* ~16ms */
//---------------------------------------------------------
// triangle - calc value of triangle function for lfos
//---------------------------------------------------------
float triangle(int dur,int pos) {
pos += dur/4;
pos %= dur;
if (pos>dur/2)
return 2*(0.5-((pos/(0.5*dur))-1));
else
return 2*((pos/(0.5*dur))-0.5);
}
//---------------------------------------------------------
// samplesToNextTurningPoint
// calculate how many samples it is to the next change
// from rising to falling in a triangle function
//---------------------------------------------------------
int samplesToNextTurningPoint(int dur, int pos) {
pos += dur/4;
return ((dur/2)-(pos%(dur/2))) % (dur/2);
}
//---------------------------------------------------------
// Voice
//---------------------------------------------------------
Voice::Voice(Fluid* f)
{
_fluid = f;
status = FLUID_VOICE_OFF;
chan = NO_CHANNEL;
key = 0;
vel = 0;
channel = 0;
sample = 0;
/* The 'sustain' and 'finished' segments of the volume / modulation
* envelope are constant. They are never affected by any modulator
* or generator. Therefore it is enough to initialize them once
* during the lifetime of the synth.
*/
volenv_data[FLUID_VOICE_ENVSUSTAIN].count = 0xffffffff;
volenv_data[FLUID_VOICE_ENVSUSTAIN].coeff = 1.0f;
volenv_data[FLUID_VOICE_ENVSUSTAIN].incr = 0.0f;
volenv_data[FLUID_VOICE_ENVSUSTAIN].min = -1.0f;
volenv_data[FLUID_VOICE_ENVSUSTAIN].max = 2.0f;
volenv_data[FLUID_VOICE_ENVFINISHED].count = 0xffffffff;
volenv_data[FLUID_VOICE_ENVFINISHED].coeff = 0.0f;
volenv_data[FLUID_VOICE_ENVFINISHED].incr = 0.0f;
volenv_data[FLUID_VOICE_ENVFINISHED].min = -1.0f;
volenv_data[FLUID_VOICE_ENVFINISHED].max = 1.0f;
modenv_data[FLUID_VOICE_ENVSUSTAIN].count = 0xffffffff;
modenv_data[FLUID_VOICE_ENVSUSTAIN].coeff = 1.0f;
modenv_data[FLUID_VOICE_ENVSUSTAIN].incr = 0.0f;
modenv_data[FLUID_VOICE_ENVSUSTAIN].min = -1.0f;
modenv_data[FLUID_VOICE_ENVSUSTAIN].max = 2.0f;
modenv_data[FLUID_VOICE_ENVFINISHED].count = 0xffffffff;
modenv_data[FLUID_VOICE_ENVFINISHED].coeff = 0.0f;
modenv_data[FLUID_VOICE_ENVFINISHED].incr = 0.0f;
modenv_data[FLUID_VOICE_ENVFINISHED].min = -1.0f;
modenv_data[FLUID_VOICE_ENVFINISHED].max = 1.0f;
}
//---------------------------------------------------------
// init
// Initialize the synthesis process
//---------------------------------------------------------
void Voice::init(Sample* _sample, Channel* _channel, int _key, int _vel,
unsigned int _id, double tuning)
{
// Note: The voice parameters will be initialized later, when the
// generators have been retrieved from the sound font. Here, only
// the 'working memory' of the voice (position in envelopes, history
// of IIR filters, position in sample etc) is initialized.
id = _id;
_noteTuning = tuning;
chan = _channel->getNum();
key = _key;
vel = _vel;
channel = _channel;
mod_count = 0;
sample = _sample;
ticks = 0;
debug = 0;
has_looped = false; // Will be set during voice_write when the 2nd loop point is reached
last_fres = -1; // The filter coefficients have to be calculated later in the DSP loop.
filter_startup = 1; // Set the filter immediately, don't fade between old and new settings
interp_method = _channel->getInterpMethod();
// vol env initialization
volenv_count = 0;
volenv_section = 0;
volenv_val = 0.0f;
amp = 0.0f; // The last value of the volume envelope, used to
// calculate the volume increment during
// processing
// mod env initialization
modenv_count = 0;
modenv_section = 0;
modenv_val = 0.0f;
/* mod lfo */
modlfo_val = 0.0; // Fixme: Retrieve from any other existing
// voice on this channel to keep LFOs in
// unison?
modlfo_pos = 0;
/* vib lfo */
viblfo_val = 0.0f; // Fixme: See mod lfo
/* Clear sample history in filter */
hist1 = 0;
hist2 = 0;
/* Set all the generators to their default value, according to SF
* 2.01 section 8.1.3 (page 48). The value of NRPN messages are
* copied from the channel to the voice's generators. The sound font
* loader overwrites them. The generator values are later converted
* into voice parameters in calculate_runtime_synthesis_parameters.
*/
fluid_gen_init(&gen[0], channel);
/* For a looped sample, this value will be overwritten as soon as the
* loop parameters are initialized (they may depend on modulators).
* This value can be kept, it is a worst-case estimate.
*/
amplitude_that_reaches_noise_floor_nonloop = FLUID_NOISE_FLOOR;
amplitude_that_reaches_noise_floor_loop = FLUID_NOISE_FLOOR;
}
//---------------------------------------------------------
// gen_set
//---------------------------------------------------------
void Voice::gen_set(int i, float val)
{
gen[i].val = val;
gen[i].flags = GEN_SET;
}
//---------------------------------------------------------
// gen_incr
//---------------------------------------------------------
void Voice::gen_incr(int i, float val)
{
gen[i].val += val;
gen[i].flags = GEN_SET;
}
//---------------------------------------------------------
// gen_get
//---------------------------------------------------------
float Voice::gen_get(int g)
{
return gen[g].val;
}
inline void Voice::calcVolEnv(int n, fluid_env_data_t *env_data)
{
float x;
/* calculate the envelope value and check for valid range */
x = env_data->coeff * volenv_val + env_data->incr * n;
if (x < env_data->min)
x = env_data->min;
else if (x > env_data->max)
x = env_data->max;
volenv_val = x;
}
std::tuple<unsigned, bool> Voice::interpolateGeneratedDSPData(unsigned n)
{
dsp_buf.resize(n, 0.0f);
std::fill(dsp_buf.begin(), dsp_buf.end(), 0.0f);
unsigned generatedFrames = 0;
switch (interp_method) {
case FLUID_INTERP_NONE:
generatedFrames = dsp_float_interpolate_none(n);
break;
case FLUID_INTERP_LINEAR:
generatedFrames = dsp_float_interpolate_linear(n);
break;
case FLUID_INTERP_4THORDER:
default:
generatedFrames = dsp_float_interpolate_4th_order(n);
break;
case FLUID_INTERP_7THORDER:
generatedFrames = dsp_float_interpolate_7th_order(n);
break;
}
/* turn off voice if short count (sample ended and not looping) or voice reached noise floor*/
if (generatedFrames < n || positionToTurnOff > 0)
off();
bool needToRunBuffFilling = generatedFrames > 0;
return std::make_tuple(generatedFrames, needToRunBuffFilling);
}
bool Voice::generateDataForDSPChain(unsigned framesBufCount)
{
/* Range checking for sample- and loop-related parameters
* Initial phase is calculated here*/
check_sample_sanity();
/******************* vol env **********************/
fluid_env_data_t* env_data = &volenv_data[volenv_section];
Sample2AmpInc.clear();
std::map<int, int> sample2VolEnvSection;
std::set<int> volumeChanges;
if (volenv_section >= FLUID_VOICE_ENVFINISHED) {
off();
return false;
}
// determine points where volume envelope changes
unsigned curVolEnvCount = volenv_count;
unsigned restN = framesBufCount;
while (curVolEnvCount + restN >= env_data->count) {
restN -= env_data->count - curVolEnvCount;
sample2VolEnvSection.insert(std::pair<int, int>(framesBufCount - restN, volenv_section));
volumeChanges.insert(framesBufCount-restN);
curVolEnvCount = 0;
volenv_section++;
env_data = &volenv_data[volenv_section];
}
sample2VolEnvSection.insert(std::pair<int, int>(framesBufCount, volenv_section));
volumeChanges.insert(framesBufCount);
fluid_check_fpe ("voice_write vol env");
/******************* mod env **********************/
/* Skip to decay phase if delay and attack envelope sections each are
* less than 100 samples long. This avoids popping noises due to the
* mod envelope being out-of-sync with the sample-based volume envelope. */
if (modenv_section < 2 && modenv_data[FLUID_VOICE_ENVDELAY].count < 100 && modenv_data[FLUID_VOICE_ENVATTACK].count < 100) {
modenv_section = 2;
modenv_val = 1.0f;
}
env_data = &modenv_data[modenv_section];
/* skip to the next section of the envelope if necessary */
while (modenv_count >= env_data->count) {
env_data = &modenv_data[++modenv_section];
modenv_count = 0;
}
/* calculate the envelope value and check for valid range */
float x = env_data->coeff * modenv_val + env_data->incr * framesBufCount;
if (x < env_data->min) {
x = env_data->min;
modenv_section++;
modenv_count = 0;
}
else if (x > env_data->max) {
x = env_data->max;
modenv_section++;
modenv_count = 0;
}
modenv_val = x;
modenv_count += framesBufCount;
fluid_check_fpe ("voice_write mod env");
/******************* mod lfo **********************/
// calculate all points where we need to consider
// the mod lfo (where it changes its slope)
int modLfoStart = -1;
if (fabs(modlfo_to_vol) > 0) {
if (ticks >= modlfo_delay)
modLfoStart = 0;
else if (framesBufCount >= modlfo_delay)
modLfoStart = modlfo_delay;
if (modLfoStart >= 0) {
if (modLfoStart > 0)
volumeChanges.insert(modLfoStart);
unsigned int modLfoNextTurn = samplesToNextTurningPoint(modlfo_dur, modlfo_pos);
while (modLfoNextTurn+modLfoStart < framesBufCount) {
volumeChanges.insert(modLfoNextTurn+modLfoStart);
modLfoNextTurn++;
modLfoNextTurn += samplesToNextTurningPoint(modlfo_dur, modLfoNextTurn);
}
}
}
fluid_check_fpe ("voice_write mod LFO");
/******************* vib lfo **********************/
if (ticks >= viblfo_delay) {
viblfo_val += viblfo_incr * framesBufCount;
if (viblfo_val > (float) 1.0) {
viblfo_incr = -viblfo_incr;
viblfo_val = (float) 2.0 - viblfo_val;
}
else if (viblfo_val < -1.0) {
viblfo_incr = -viblfo_incr;
viblfo_val = (float) -2.0 - viblfo_val;
}
}
fluid_check_fpe ("voice_write Vib LFO");
/******************* amplitude **********************/
if (volenv_section == FLUID_VOICE_ENVDELAY) {
return false; /* The volume amplitude is in hold phase. No sound is produced. */
}
qreal oldTargetAmp = amp;
int lastPos = 0;
auto oldVolEnvSection = sample2VolEnvSection.begin();
auto curVolEnvSection = oldVolEnvSection;
for (auto curPos : volumeChanges)
{
if (modLfoStart >= 0 && curPos >= modLfoStart)
modlfo_val = triangle(modlfo_dur, modlfo_pos+curPos-modLfoStart);
else
modlfo_val = 0;
// never calculate anything for the very first sample
// everything should have been calculated in the last
// cycle - it would also cause a divion by zero later
if (curPos == 0) {
curPos = 1;
// if we should calculate for position 1 already make sure we don't do it twice
// could lead to curPos==lastPos which causes devision by zero
if (volumeChanges.find(1) != volumeChanges.end())
volumeChanges.erase(volumeChanges.find(1));
}
// just go to the next volume section if we're below last volume point
if (curPos >= curVolEnvSection->first && (unsigned int) curVolEnvSection->first < framesBufCount)
curVolEnvSection++;
volenv_count += curPos-lastPos;
calcVolEnv(curPos-lastPos, &volenv_data[oldVolEnvSection->second]);
volenv_section = oldVolEnvSection->second;
qreal target_amp {0.0}; /* target amplitude */
if (volenv_section <= FLUID_VOICE_ENVATTACK) {
/* the envelope is in the attack section: ramp linearly to max value.
* A positive modlfo_to_vol should increase volume (negative attenuation).
*/
target_amp = fluid_atten2amp (attenuation)
* fluid_cb2amp (modlfo_val * -modlfo_to_vol)
* volenv_val;
}
else {
//float amplitude_that_reaches_noise_floor;
//float amp_max;
target_amp = fluid_atten2amp (attenuation)
* fluid_cb2amp (960.0f * (1.0f - volenv_val)
+ modlfo_val * -modlfo_to_vol);
/* A voice can be turned off, when an estimate for the volume
* (upper bound) falls below that volume, that will drop the
* sample below the noise floor.
*/
/* If the loop amplitude is known, we can use it if the voice loop is within
* the sample loop
*/
float amplitude_that_reaches_noise_floor;
/* Is the playing pointer already in the loop? */
if (has_looped)
amplitude_that_reaches_noise_floor = amplitude_that_reaches_noise_floor_loop;
else
amplitude_that_reaches_noise_floor = amplitude_that_reaches_noise_floor_nonloop;
/* voice->attenuation_min is a lower boundary for the attenuation
* now and in the future (possibly 0 in the worst case). Now the
* amplitude of sample and volenv cannot exceed amp_max (since
* volenv_val can only drop):
*/
float amp_max = fluid_atten2amp (min_attenuation_cB) * volenv_val;
/* And if amp_max is already smaller than the known amplitude,
* which will attenuate the sample below the noise floor, then we
* can safely turn off the voice. Duh. */
if (amp_max < amplitude_that_reaches_noise_floor) {
positionToTurnOff = curPos;
}
}
if (curVolEnvSection->second != oldVolEnvSection->second) {
if (oldVolEnvSection->second == FLUID_VOICE_ENVDECAY) {
env_data = &volenv_data[oldVolEnvSection->second];
volenv_val = env_data->min * env_data->coeff;
}
volenv_count = 0;
oldVolEnvSection = curVolEnvSection;
}
/* Volume increment to go from voice->amp to target_amp in FLUID_BUFSIZE steps */
amp_incr = (target_amp - oldTargetAmp) / (curPos - lastPos);
lastPos = curPos;
Sample2AmpInc.insert(std::pair<int, qreal>(curPos, amp_incr));
// if voice is turned off after this no need to calculate any more values
if (positionToTurnOff > 0)
break;
oldTargetAmp = target_amp;
}
if (modLfoStart >= 0) {
modlfo_pos += framesBufCount - modLfoStart;
modlfo_val = triangle(modlfo_dur, modlfo_pos-modLfoStart);
}
fluid_check_fpe ("voice_write amplitude calculation");
/* Calculate the number of samples, that the DSP loop advances
* through the original waveform with each step in the output
* buffer. It is the ratio between the frequencies of original
* waveform and output waveform.*/
{
float cent = pitch + modlfo_val * modlfo_to_pitch
+ viblfo_val * viblfo_to_pitch
+ modenv_val * modenv_to_pitch;
phase_incr = _fluid->ct2hz_real(cent) / root_pitch_hz;
}
/* if phase_incr is not advancing, set it to the minimum fraction value (prevent stuckage) */
if (phase_incr == 0)
phase_incr = 1;
/*************** resonant filter ******************/
/* calculate the frequency of the resonant filter in Hz */
float _fres = _fluid->ct2hz_real(fres
+ modlfo_val * modlfo_to_fc
+ modenv_val * modenv_to_fc);
/* FIXME - Still potential for a click during turn on, can we interpolate
between 20khz cutoff and 0 Q? */
/* I removed the optimization of turning the filter off when the
* resonance frequence is above the maximum frequency. Instead, the
* filter frequency is set to a maximum of 0.45 times the sampling
* rate. For a 44100 kHz sampling rate, this amounts to 19845
* Hz. The reason is that there were problems with anti-aliasing when the
* synthesizer was run at lower sampling rates. Thanks to Stephan
* Tassart for pointing me to this bug. By turning the filter on and
* clipping the maximum filter frequency at 0.45*srate, the filter
* is used as an anti-aliasing filter. */
if (_fres > 0.45f * _fluid->sample_rate)
_fres = 0.45f * _fluid->sample_rate;
else if (_fres < 5)
_fres = 5;
/* if filter enabled and there is a significant frequency change.. */
if ((qAbs(_fres - last_fres) > 0.01)) {
/* The filter coefficients have to be recalculated (filter
* parameters have changed). Recalculation for various reasons is
* forced by setting last_fres to -1. The flag filter_startup
* indicates, that the DSP loop runs for the first time, in this
* case, the filter is set directly, instead of smoothly fading
* between old and new settings.
*
* Those equations from Robert Bristow-Johnson's `Cookbook
* formulae for audio EQ biquad filter coefficients', obtained
* from Harmony-central.com / Computer / Programming. They are
* the result of the bilinear transform on an analogue filter
* prototype. To quote, `BLT frequency warping has been taken
* into account for both significant frequency relocation and for
* bandwidth readjustment'. */
float omega = (float) (2.0 * M_PI * (_fres / ((float) _fluid->sample_rate)));
float sin_coeff = (float) sin(omega);
float cos_coeff = (float) cos(omega);
float alpha_coeff = sin_coeff / (2.0f * q_lin);
float a0_inv = 1.0f / (1.0f + alpha_coeff);
/* Calculate the filter coefficients. All coefficients are
* normalized by a0. Think of `a1' as `a1/a0'.
*
* Here a couple of multiplications are saved by reusing common expressions.
* The original equations should be:
* b0=(1.-cos_coeff)*a0_inv*0.5*voice->filter_gain;
* b1=(1.-cos_coeff)*a0_inv*voice->filter_gain;
* b2=(1.-cos_coeff)*a0_inv*0.5*voice->filter_gain; */
float a1_temp = -2.0f * cos_coeff * a0_inv;
float a2_temp = (1.0f - alpha_coeff) * a0_inv;
float b1_temp = (1.0f - cos_coeff) * a0_inv * filter_gain;
/* both b0 -and- b2 */
float b02_temp = b1_temp * 0.5f;
if (filter_startup) {
/* The filter is calculated, because the voice was started up.
* In this case set the filter coefficients without delay.
*/
a1 = a1_temp;
a2 = a2_temp;
b02 = b02_temp;
b1 = b1_temp;
filter_coeff_incr_count = 0;
filter_startup = 0;
//printf("Setting initial filter coefficients.\n");
}
else {
/* The filter frequency is changed. Calculate an increment
* factor, so that the new setting is reached after one buffer
* length. x_incr is added to the current value FLUID_BUFSIZE
* times. The length is arbitrarily chosen. Longer than one
* buffer will sacrifice some performance, though. Note: If
* the filter is still too 'grainy', then increase this number
* at will.
*/
#define FILTER_TRANSITION_SAMPLES 64 // (FLUID_BUFSIZE)
a1_incr = (a1_temp - a1) / FILTER_TRANSITION_SAMPLES;
a2_incr = (a2_temp - a2) / FILTER_TRANSITION_SAMPLES;
b02_incr = (b02_temp - b02) / FILTER_TRANSITION_SAMPLES;
b1_incr = (b1_temp - b1) / FILTER_TRANSITION_SAMPLES;
/* Have to add the increments filter_coeff_incr_count times. */
filter_coeff_incr_count = FILTER_TRANSITION_SAMPLES;
}
last_fres = _fres;
fluid_check_fpe ("voice_write filter calculation");
}
fluid_check_fpe ("voice_write DSP coefficients");
return true;
}
static float* shiftBufferPosition(unsigned shift, float* buff)
{
float* resBuffPosition = buff;
for (unsigned i = 0; i < shift; ++i) {
++resBuffPosition; //left channel
++resBuffPosition; //right channel
}
return resBuffPosition;
}
//-----------------------------------------------------------------------------
// write
//
// This is where it all happens. This function is called by the
// synthesizer to generate the sound samples. The synthesizer passes
// four audio buffers: left, right, reverb out, and chorus out.
//
// The biggest part of this function sets the correct values for all
// the dsp parameters (all the control data boil down to only a few
// dsp parameters). The dsp routine is #included in several places (fluid_dsp_core.c).
//-----------------------------------------------------------------------------
void Voice::write(unsigned n, float* out, float* reverb, float* chorus)
{
/* make sure we're playing and that we have sample data */
if (!PLAYING())
return;
if (!sample) {
//printf("!sample\n");
off();
return;
}
/*
/ ------- CACHING ALGORITHM -------
/ If cached frames exist and number of required frames is less than cache size
/ apply effects to the required number of frames from cache, put cache to buffer
/ Else
/ put all cached frames to buffer
/ (buffer* is a buffer after putting left cache data)
/ generate DSP data and interpolation for buffer* size data or required buffer size if buffer* is too small
/ fill cache data with raw buffer* data
/ apply effects to cache and put cache data to raw buffer*
*/
if (n <= _cachedFrames) {
effects(_initialCacheFrames - _cachedFrames, n, out, reverb, chorus);
_cachedFrames -= n;
}
else {
const unsigned leftBufferFramesToFill = n - _cachedFrames; //must be called before setting null to _cachedFrames
unsigned buffShiftAfterApplyingCache = 0;
if (_cachedFrames > 0) {
buffShiftAfterApplyingCache = _cachedFrames;
effects(_initialCacheFrames - _cachedFrames, _cachedFrames, out, reverb, chorus);
_cachedFrames = 0;
}
const unsigned requiredNumberOfFramesToGenerateEnvelope = FLUID_VOICE_ENVLAST * volenv_data[FLUID_VOICE_ENVDELAY].count;
const unsigned framesToGenerateData = std::max(leftBufferFramesToFill, requiredNumberOfFramesToGenerateEnvelope);
if (generateDataForDSPChain(framesToGenerateData)) {
auto interpolationRes = interpolateGeneratedDSPData(framesToGenerateData);
if (std::get<1>(interpolationRes)) {
_initialCacheFrames = std::get<0>(interpolationRes);
float* shiftedOut = shiftBufferPosition(buffShiftAfterApplyingCache, out);
float* shiftedReverb = shiftBufferPosition(buffShiftAfterApplyingCache, reverb);
float* shiftedChorus = shiftBufferPosition(buffShiftAfterApplyingCache, chorus);
effects(0, leftBufferFramesToFill, shiftedOut, shiftedReverb, shiftedChorus);
_cachedFrames = _initialCacheFrames;
_cachedFrames -= std::min(leftBufferFramesToFill, _cachedFrames); //to keep positive
}
}
}
ticks += n;
}
//---------------------------------------------------------
// voice_start
//---------------------------------------------------------
void Voice::voice_start()
{
/* The maximum volume of the loop is calculated and cached once for each
* sample with its nominal loop settings. This happens, when the sample is used
* for the first time.*/
/*
* in this function we calculate the values of all the parameters. the
* parameters are converted to their most useful unit for the DSP
* algorithm, for example, number of samples instead of
* timecents. Some parameters keep their "perceptual" unit and
* conversion will be done in the DSP function. This is the case, for
* example, for the pitch since it is modulated by the controllers in
* cents. */
static const int list_of_generators_to_initialize[35] = {
GEN_STARTADDROFS, // SF2.01 page 48 #0
GEN_ENDADDROFS, // #1
GEN_STARTLOOPADDROFS, // #2
GEN_ENDLOOPADDROFS, // #3
// GEN_STARTADDRCOARSEOFS see comment below [1] #4
GEN_MODLFOTOPITCH, // #5
GEN_VIBLFOTOPITCH, // #6
GEN_MODENVTOPITCH, // #7
GEN_FILTERFC, // #8
GEN_FILTERQ, // #9
GEN_MODLFOTOFILTERFC, // #10
GEN_MODENVTOFILTERFC, // #11
// GEN_ENDADDRCOARSEOFS [1] #12
GEN_MODLFOTOVOL, // #13
// not defined #14
GEN_CHORUSSEND, // #15
GEN_REVERBSEND, // #16
GEN_PAN, // #17
// not defined #18
// not defined #19
// not defined #20
GEN_MODLFODELAY, // #21
GEN_MODLFOFREQ, // #22
GEN_VIBLFODELAY, // #23
GEN_VIBLFOFREQ, // #24
GEN_MODENVDELAY, // #25
GEN_MODENVATTACK, // #26
GEN_MODENVHOLD, // #27
GEN_MODENVDECAY, // #28
// GEN_MODENVSUSTAIN [1] #29
GEN_MODENVRELEASE, // #30
// GEN_KEYTOMODENVHOLD [1] #31
// GEN_KEYTOMODENVDECAY [1] #32
GEN_VOLENVDELAY, // #33
GEN_VOLENVATTACK, // #34
GEN_VOLENVHOLD, // #35
GEN_VOLENVDECAY, // #36
// GEN_VOLENVSUSTAIN [1] #37
GEN_VOLENVRELEASE, // #38
// GEN_KEYTOVOLENVHOLD [1] #39
// GEN_KEYTOVOLENVDECAY [1] #40
// GEN_STARTLOOPADDRCOARSEOFS [1] #45
GEN_KEYNUM, // #46
GEN_VELOCITY, // #47
GEN_ATTENUATION, // #48
// GEN_ENDLOOPADDRCOARSEOFS [1] #50
// GEN_COARSETUNE [1] #51
// GEN_FINETUNE [1] #52
GEN_OVERRIDEROOTKEY, // #58
GEN_PITCH, // ---
-1 // end-of-list marker
};
/* When the voice is made ready for the synthesis process, a lot of
* voice-internal parameters have to be calculated.
*
* At this point, the sound font has already set the -nominal- value
* for all generators (excluding GEN_PITCH). Most generators can be
* modulated - they include a nominal value and an offset (which
* changes with velocity, note number, channel parameters like
* aftertouch, mod wheel...) Now this offset will be calculated as
* follows:
*
* - Process each modulator once.
* - Calculate its output value.
* - Find the target generator.
* - Add the output value to the modulation value of the generator.
*
* Note: The generators have been initialized with
* fluid_gen_set_default_values.
*/
for (int i = 0; i < mod_count; i++) {
Mod* m = &mod[i];
float modval = m->get_value(channel, this);
int dest_gen_index = m->dest;
Generator* dest_gen = &gen[dest_gen_index];
dest_gen->mod += modval;
}
/* Now the generators are initialized, nominal and modulation value.
* The voice parameters (which depend on generators) are calculated
* with update_param. Processing the list of generator
* changes will calculate each voice parameter once.
*
* Note [1]: Some voice parameters depend on several generators. For
* example, the pitch depends on GEN_COARSETUNE, GEN_FINETUNE and
* GEN_PITCH. voice->pitch. Unnecessary recalculation is avoided
* by removing all but one generator from the list of voice
* parameters. Same with GEN_XXX and GEN_XXXCOARSE: the
* initialisation list contains only GEN_XXX.
*/
/* Calculate the voice parameter(s) dependent on each generator. */
for (int i = 0; list_of_generators_to_initialize[i] != -1; i++)
update_param(list_of_generators_to_initialize[i]);
/* Make an estimate on how loud this voice can get at any time (attenuation). */
min_attenuation_cB = get_lower_boundary_for_attenuation();
// qDebug("DELAY (%d) %d", FLUID_VOICE_ENVDELAY,volenv_data[FLUID_VOICE_ENVDELAY].count);
// qDebug("ATTACK (%d) %d", FLUID_VOICE_ENVATTACK,volenv_data[FLUID_VOICE_ENVATTACK].count);
// qDebug("HOLD (%d) %d", FLUID_VOICE_ENVHOLD, volenv_data[FLUID_VOICE_ENVHOLD].count);
// qDebug("DECAY (%d) %d", FLUID_VOICE_ENVDECAY, volenv_data[FLUID_VOICE_ENVDECAY].count);
// qDebug("SUSTAIN (%d) %d", FLUID_VOICE_ENVSUSTAIN, volenv_data[FLUID_VOICE_ENVSUSTAIN].count);
// qDebug("RELEASE (%d) %d", FLUID_VOICE_ENVRELEASE, volenv_data[FLUID_VOICE_ENVRELEASE].count);
/* Force setting of the phase at the first DSP loop run
* This cannot be done earlier, because it depends on modulators.
*/
check_sample_sanity_flag = FLUID_SAMPLESANITY_STARTUP;
positionToTurnOff = -1;
status = FLUID_VOICE_ON;
}
//---------------------------------------------------------
// fluid_voice_calculate_gen_pitch
//---------------------------------------------------------
void Voice::calculate_gen_pitch()
{
float x;
/* The GEN_PITCH is a hack to fit the pitch bend controller into the
* modulator paradigm. Now the nominal pitch of the key is set.
* Note about SCALETUNE: SF2.01 8.1.3 says, that this generator is a
* non-realtime parameter. So we don't allow modulation (as opposed
* to _GEN(voice, GEN_SCALETUNE) When the scale tuning is varied,
* one key remains fixed. Here C3 (MIDI number 60) is used.
*/
//if (channel->tuning != 0) {
/* pitch(scalekey) + scale * (pitch(key) - pitch(scalekey)) */
x = _fluid->getPitch((int)(root_pitch / 100.0f));
gen[GEN_PITCH].val = _noteTuning + (x + (gen[GEN_SCALETUNE].val / 100.0f * (_fluid->getPitch(key) - x)));
// }
//else {
// gen[GEN_PITCH].val = _noteTuning + (gen[GEN_SCALETUNE].val * (key - root_pitch / 100.0f) + root_pitch);
// }
}
/*
* calculate_hold_decay_frames
*/
int Voice::calculate_hold_decay_frames(int gen_base, int gen_key2base, int is_decay)
{
/* Purpose:
*
* Returns the number of DSP loops, that correspond to the hold
* (is_decay=0) or decay (is_decay=1) time.
* gen_base=GEN_VOLENVHOLD, GEN_VOLENVDECAY, GEN_MODENVHOLD,
* GEN_MODENVDECAY gen_key2base=GEN_KEYTOVOLENVHOLD,
* GEN_KEYTOVOLENVDECAY, GEN_KEYTOMODENVHOLD, GEN_KEYTOMODENVDECAY
*
* SF2.01 section 8.4.3 # 31, 32, 39, 40
* GEN_KEYTOxxxENVxxx uses key 60 as 'origin'.
* The unit of the generator is timecents per key number.
* If KEYTOxxxENVxxx is 100, a key one octave over key 60 (72)
* will cause (60-72)*100=-1200 timecents of time variation.
* The time is cut in half.
*/
float timecents = (GEN(gen_base) + GEN(gen_key2base) * (60.0 - key));
/* Range checking */
if (is_decay){
/* SF 2.01 section 8.1.3 # 28, 36 */
if (timecents > 8000.0)
timecents = 8000.0;
}
else {
/* SF 2.01 section 8.1.3 # 27, 35 */
if (timecents > 5000)
timecents = 5000.0;
/* SF 2.01 section 8.1.2 # 27, 35:
* The most negative number indicates no hold time
*/
if (timecents <= -32768.)
return 0;
}
/* SF 2.01 section 8.1.3 # 27, 28, 35, 36 */
if (timecents < -12000.0)
timecents = -12000.0;
float seconds = fluid_tc2sec(timecents);
return (int)((float)_fluid->sample_rate * seconds);
}
/*
* update_param
*
* Purpose:
*
* The value of a generator (gen) has changed. (The different
* generators are listed in fluid.h, or in SF2.01 page 48-49)
* Now the dependent 'voice' parameters are calculated.
*
* fluid_voice_update_param can be called during the setup of the
* voice (to calculate the initial value for a voice parameter), or
* during its operation (a generator has been changed due to
* real-time parameter modifications like pitch-bend).
*
* Note: The generator holds three values: The base value .val, an
* offset caused by modulators .mod, and an offset caused by the
* NRPN system. _GEN(voice, generator_enumerator) returns the sum
* of all three.
*/
void Voice::update_param(int _gen)
{
double q_dB;
float x;
float y;
unsigned int count;
// Alternate attenuation scale used by EMU10K1 cards when setting the attenuation at the preset or instrument level within the SoundFont bank.
static const float ALT_ATTENUATION_SCALE = 0.4f;
double gain = 1.0 / 32768.0f;
switch (_gen) {
case GEN_PAN:
/* range checking is done in the fluid_pan function */
pan = GEN(GEN_PAN);
amp_left = fluid_pan(pan, 1) * gain;
amp_right = fluid_pan(pan, 0) * gain;
break;
case GEN_ATTENUATION:
attenuation = gen[GEN_ATTENUATION].val * ALT_ATTENUATION_SCALE + gen[GEN_ATTENUATION].mod + gen[GEN_ATTENUATION].nrpn;
/* Range: SF2.01 section 8.1.3 # 48
* Motivation for range checking:
* OHPiano.SF2 sets initial attenuation to a whooping -96 dB
*/
attenuation = qBound(0.0f, attenuation, 1440.0f);
break;
/* The pitch is calculated from three different generators.
* Read comment in fluid.h about GEN_PITCH.
*/
case GEN_PITCH:
case GEN_COARSETUNE:
case GEN_FINETUNE:
/* The testing for allowed range is done in 'fluid_ct2hz' */
pitch = GEN(GEN_PITCH) + 100.0f * GEN(GEN_COARSETUNE) + GEN(GEN_FINETUNE);
break;
case GEN_REVERBSEND:
/* The generator unit is 'tenths of a percent'. */
// reverb_send = GEN(GEN_REVERBSEND) / 1000.0f;
reverb_send = float(channel->cc[EFFECTS_DEPTH1]) / 128.0;
// fluid_clip(reverb_send, 0.0, 1.0);
amp_reverb = reverb_send * gain;
break;
case GEN_CHORUSSEND:
/* The generator unit is 'tenths of a percent'. */
chorus_send = GEN(GEN_CHORUSSEND) / 1000.0f;
fluid_clip(chorus_send, 0.0, 1.0);
amp_chorus = chorus_send * gain;
break;
case GEN_OVERRIDEROOTKEY:
/* This is a non-realtime parameter. Therefore the .mod part of the generator
* can be neglected.
* NOTE: origpitch sets MIDI root note while pitchadj is a fine tuning amount
* which offsets the original rate. This means that the fine tuning is
* inverted with respect to the root note (so subtract it, not add).
*/
if (sample != 0) {
if (gen[GEN_OVERRIDEROOTKEY].val > -1) { //FIXME: use flag instead of -1
root_pitch = gen[GEN_OVERRIDEROOTKEY].val * 100.0f - sample->pitchadj;
}
else {
root_pitch = sample->origpitch * 100.0f - sample->pitchadj;
}
root_pitch_hz = _fluid->ct2hz(root_pitch);
root_pitch_hz *= (float) _fluid->sample_rate / sample->samplerate;
/* voice pitch depends on voice root_pitch, so calculate voice pitch now */
calculate_gen_pitch();
}
break;
case GEN_FILTERFC:
/* The resonance frequency is converted from absolute cents to
* midicents .val and .mod are both used, this permits real-time
* modulation. The allowed range is tested in the 'fluid_ct2hz'
* function [PH,20021214]
*/
fres = GEN(GEN_FILTERFC);
/* The synthesis loop will have to recalculate the filter
* coefficients. */
last_fres = -1.0f;
break;
case GEN_FILTERQ:
/* The generator contains 'centibels' (1/10 dB) => divide by 10 to
* obtain dB
*/
q_dB = GEN(GEN_FILTERQ) / 10.0f;
/* Range: SF2.01 section 8.1.3 # 8 (convert from cB to dB => /10) */
fluid_clip(q_dB, 0.0f, 96.0f);
/* Short version: Modify the Q definition in a way, that a Q of 0
* dB leads to no resonance hump in the freq. response.
*
* Long version: From SF2.01, page 39, item 9 (initialFilterQ):
* "The gain at the cutoff frequency may be less than zero when
* zero is specified". Assume q_dB=0 / q_lin=1: If we would leave
* q as it is, then this results in a 3 dB hump slightly below
* fc. At fc, the gain is exactly the DC gain (0 dB). What is
* (probably) meant here is that the filter does not show a
* resonance hump for q_dB=0. In this case, the corresponding
* q_lin is 1/sqrt(2)=0.707. The filter should have 3 dB of
* attenuation at fc now. In this case Q_dB is the height of the
* resonance peak not over the DC gain, but over the frequency
* response of a non-resonant filter. This idea is implemented as
* follows:
*/
q_dB -= 3.01f;
/* The 'sound font' Q is defined in dB. The filter needs a linear
q. Convert.
*/
q_lin = (float) (pow(10.0f, q_dB / 20.0f));
/* SF 2.01 page 59:
*
* The SoundFont specs ask for a gain reduction equal to half the
* height of the resonance peak (Q). For example, for a 10 dB
* resonance peak, the gain is reduced by 5 dB. This is done by
* multiplying the total gain with sqrt(1/Q). `Sqrt' divides dB
* by 2 (100 lin = 40 dB, 10 lin = 20 dB, 3.16 lin = 10 dB etc)
* The gain is later factored into the 'b' coefficients
* (numerator of the filter equation). This gain factor depends
* only on Q, so this is the right place to calculate it.
*/
filter_gain = (float) (1.0 / sqrt(q_lin));
/* The synthesis loop will have to recalculate the filter coefficients. */
last_fres = -1.;
break;
case GEN_MODLFOTOPITCH:
modlfo_to_pitch = GEN(GEN_MODLFOTOPITCH);
fluid_clip(modlfo_to_pitch, -12000.0, 12000.0);
break;
case GEN_MODLFOTOVOL:
modlfo_to_vol = GEN(GEN_MODLFOTOVOL);
fluid_clip(modlfo_to_vol, -960.0, 960.0);
break;
case GEN_MODLFOTOFILTERFC:
modlfo_to_fc = GEN(GEN_MODLFOTOFILTERFC);
fluid_clip(modlfo_to_fc, -12000, 12000);
break;
case GEN_MODLFODELAY:
x = GEN(GEN_MODLFODELAY);
fluid_clip(x, -12000.0f, 5000.0f);
modlfo_delay = (unsigned int) (_fluid->sample_rate * fluid_tc2sec_delay(x));
break;
case GEN_MODLFOFREQ:
{
/* - the frequency is converted into a delta value, per frame
* - the delay into a sample delay
*/
unsigned int old_modlfo_dur = modlfo_dur;
x = GEN(GEN_MODLFOFREQ);
fluid_clip(x, -16000.0f, 4500.0f);
modlfo_dur = _fluid->sample_rate / fluid_act2hz(x);
if (old_modlfo_dur > 0)
modlfo_pos = (modlfo_pos/old_modlfo_dur) * modlfo_dur;
break;
}
case GEN_VIBLFOFREQ:
/* vib lfo
*
* - the frequency is converted into a delta value per frame
* - the delay into a sample delay
*/
x = GEN(GEN_VIBLFOFREQ);
fluid_clip(x, -16000.0f, 4500.0f);
viblfo_incr = (4.0f * fluid_act2hz(x) / _fluid->sample_rate);
break;
case GEN_VIBLFODELAY:
x = GEN(GEN_VIBLFODELAY);
fluid_clip(x, -12000.0f, 5000.0f);
viblfo_delay = (unsigned int) (_fluid->sample_rate * fluid_tc2sec_delay(x));
break;
case GEN_VIBLFOTOPITCH:
viblfo_to_pitch = GEN(GEN_VIBLFOTOPITCH);
fluid_clip(viblfo_to_pitch, -12000.0, 12000.0);
break;
case GEN_KEYNUM:
/* GEN_KEYNUM: SF2.01 page 46, item 46
*
* If this generator is active, it forces the key number to its
* value. Non-realtime controller.
*
* There is a flag, which should indicate, whether a generator is
* enabled or not. But here we rely on the default value of -1.
*/
x = GEN(GEN_KEYNUM);
if (x >= 0)
key = x;
break;
case GEN_VELOCITY:
/* GEN_VELOCITY: SF2.01 page 46, item 47
*
* If this generator is active, it forces the velocity to its
* value. Non-realtime controller.
*
* There is a flag, which should indicate, whether a generator is
* enabled or not. But here we rely on the default value of -1.
*/
x = GEN(GEN_VELOCITY);
if (x > 0)
vel = x;
break;
case GEN_MODENVTOPITCH:
modenv_to_pitch = GEN(GEN_MODENVTOPITCH);
fluid_clip(modenv_to_pitch, -12000.0, 12000.0);
break;
case GEN_MODENVTOFILTERFC:
modenv_to_fc = GEN(GEN_MODENVTOFILTERFC);
/* Range: SF2.01 section 8.1.3 # 1
* Motivation for range checking:
* Filter is reported to make funny noises now and then
*/
fluid_clip(modenv_to_fc, -12000.0, 12000.0);
break;
/* sample start and ends points
*
* Range checking is initiated via the
* check_sample_sanity flag,
* because it is impossible to check here:
* During the voice setup, all modulators are processed, while
* the voice is inactive. Therefore, illegal settings may
* occur during the setup (for example: First move the loop
* end point ahead of the loop start point => invalid, then
* move the loop start point forward => valid again.
*/
case GEN_STARTADDROFS: /* SF2.01 section 8.1.3 # 0 */
case GEN_STARTADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 4 */
if (sample != 0) {
start = (sample->start
+ (int) GEN(GEN_STARTADDROFS)
+ 32768 * (int) GEN(GEN_STARTADDRCOARSEOFS));
check_sample_sanity_flag = FLUID_SAMPLESANITY_CHECK;
}
break;
case GEN_ENDADDROFS: /* SF2.01 section 8.1.3 # 1 */
case GEN_ENDADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 12 */
if (sample != 0) {
end = (sample->end
+ (int) GEN(GEN_ENDADDROFS)
+ 32768 * (int) GEN(GEN_ENDADDRCOARSEOFS));
check_sample_sanity_flag = FLUID_SAMPLESANITY_CHECK;
}
break;
case GEN_STARTLOOPADDROFS: /* SF2.01 section 8.1.3 # 2 */
case GEN_STARTLOOPADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 45 */
if (sample != 0) {
loopstart = (sample->loopstart
+ (int) GEN(GEN_STARTLOOPADDROFS)
+ 32768 * (int) GEN(GEN_STARTLOOPADDRCOARSEOFS));
check_sample_sanity_flag = FLUID_SAMPLESANITY_CHECK;
}
break;
case GEN_ENDLOOPADDROFS: /* SF2.01 section 8.1.3 # 3 */
case GEN_ENDLOOPADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 50 */
if (sample != 0) {
loopend = (sample->loopend
+ (int) GEN(GEN_ENDLOOPADDROFS)
+ 32768 * (int) GEN(GEN_ENDLOOPADDRCOARSEOFS));
check_sample_sanity_flag = FLUID_SAMPLESANITY_CHECK;
}
break;
/* Conversion functions differ in range limit */
#define NUM_FRAMES_DELAY(_v) (unsigned int) (_fluid->sample_rate * fluid_tc2sec_delay(_v))
#define NUM_FRAMES_ATTACK(_v) (unsigned int) (_fluid->sample_rate * fluid_tc2sec_attack(_v))
#define NUM_FRAMES_RELEASE(_v) (unsigned int) (_fluid->sample_rate * fluid_tc2sec_release(_v))
/* volume envelope
*
* - delay and hold times are converted to absolute number of samples
* - sustain is converted to its absolute value
* - attack, decay and release are converted to their increment per sample
*/
case GEN_VOLENVDELAY: /* SF2.01 section 8.1.3 # 33 */
x = GEN(GEN_VOLENVDELAY);
fluid_clip(x, -12000.0f, 5000.0f);
count = NUM_FRAMES_DELAY(x);
volenv_data[FLUID_VOICE_ENVDELAY].count = count;
volenv_data[FLUID_VOICE_ENVDELAY].coeff = 0.0f;
volenv_data[FLUID_VOICE_ENVDELAY].incr = 0.0f;
volenv_data[FLUID_VOICE_ENVDELAY].min = -1.0f;
volenv_data[FLUID_VOICE_ENVDELAY].max = 1.0f;
break;
case GEN_VOLENVATTACK: /* SF2.01 section 8.1.3 # 34 */
x = GEN(GEN_VOLENVATTACK);
fluid_clip(x, -12000.0f, 8000.0f);
count = 1 + NUM_FRAMES_ATTACK(x);
volenv_data[FLUID_VOICE_ENVATTACK].count = count;
volenv_data[FLUID_VOICE_ENVATTACK].coeff = 1.0f;
volenv_data[FLUID_VOICE_ENVATTACK].incr = count ? 1.0f / count : 0.0f;
volenv_data[FLUID_VOICE_ENVATTACK].min = -1.0f;
volenv_data[FLUID_VOICE_ENVATTACK].max = 1.0f;
break;
case GEN_VOLENVHOLD: /* SF2.01 section 8.1.3 # 35 */
case GEN_KEYTOVOLENVHOLD: /* SF2.01 section 8.1.3 # 39 */
count = calculate_hold_decay_frames(GEN_VOLENVHOLD, GEN_KEYTOVOLENVHOLD, 0); /* 0 means: hold */
volenv_data[FLUID_VOICE_ENVHOLD].count = count;
volenv_data[FLUID_VOICE_ENVHOLD].coeff = 1.0f;
volenv_data[FLUID_VOICE_ENVHOLD].incr = 0.0f;
volenv_data[FLUID_VOICE_ENVHOLD].min = -1.0f;
volenv_data[FLUID_VOICE_ENVHOLD].max = 2.0f;
break;
case GEN_VOLENVDECAY: /* SF2.01 section 8.1.3 # 36 */
case GEN_VOLENVSUSTAIN: /* SF2.01 section 8.1.3 # 37 */
case GEN_KEYTOVOLENVDECAY: /* SF2.01 section 8.1.3 # 40 */
y = 1.0f - 0.001f * GEN(GEN_VOLENVSUSTAIN);
fluid_clip(y, 0.0f, 1.0f);
count = calculate_hold_decay_frames(GEN_VOLENVDECAY, GEN_KEYTOVOLENVDECAY, 1); /* 1 for decay */
volenv_data[FLUID_VOICE_ENVDECAY].count = count;
volenv_data[FLUID_VOICE_ENVDECAY].coeff = 1.0f;
volenv_data[FLUID_VOICE_ENVDECAY].incr = count ? -1.0f / count : 0.0f;
volenv_data[FLUID_VOICE_ENVDECAY].min = y;
volenv_data[FLUID_VOICE_ENVDECAY].max = 2.0f;
break;
case GEN_VOLENVRELEASE: /* SF2.01 section 8.1.3 # 38 */
x = GEN(GEN_VOLENVRELEASE);
fluid_clip(x, FLUID_MIN_VOLENVRELEASE, 8000.0f);
count = 1 + NUM_FRAMES_RELEASE(x);
volenv_data[FLUID_VOICE_ENVRELEASE].count = count;
volenv_data[FLUID_VOICE_ENVRELEASE].coeff = 1.0f;
volenv_data[FLUID_VOICE_ENVRELEASE].incr = count ? -1.0f / count : 0.0f;
volenv_data[FLUID_VOICE_ENVRELEASE].min = 0.0f;
volenv_data[FLUID_VOICE_ENVRELEASE].max = 1.0f;
break;
/* Modulation envelope */
case GEN_MODENVDELAY: /* SF2.01 section 8.1.3 # 25 */
x = GEN(GEN_MODENVDELAY);
fluid_clip(x, -12000.0f, 5000.0f);
modenv_data[FLUID_VOICE_ENVDELAY].count = NUM_FRAMES_DELAY(x);
modenv_data[FLUID_VOICE_ENVDELAY].coeff = 0.0f;
modenv_data[FLUID_VOICE_ENVDELAY].incr = 0.0f;
modenv_data[FLUID_VOICE_ENVDELAY].min = -1.0f;
modenv_data[FLUID_VOICE_ENVDELAY].max = 1.0f;
break;
case GEN_MODENVATTACK: /* SF2.01 section 8.1.3 # 26 */
x = GEN(GEN_MODENVATTACK);
fluid_clip(x, -12000.0f, 8000.0f);
count = 1 + NUM_FRAMES_ATTACK(x);
modenv_data[FLUID_VOICE_ENVATTACK].count = count;
modenv_data[FLUID_VOICE_ENVATTACK].coeff = 1.0f;
modenv_data[FLUID_VOICE_ENVATTACK].incr = count ? 1.0f / count : 0.0f;
modenv_data[FLUID_VOICE_ENVATTACK].min = -1.0f;
modenv_data[FLUID_VOICE_ENVATTACK].max = 1.0f;
break;
case GEN_MODENVHOLD: /* SF2.01 section 8.1.3 # 27 */
case GEN_KEYTOMODENVHOLD: /* SF2.01 section 8.1.3 # 31 */
count = calculate_hold_decay_frames(GEN_MODENVHOLD, GEN_KEYTOMODENVHOLD, 0); /* 1 means: hold */
modenv_data[FLUID_VOICE_ENVHOLD].count = count;
modenv_data[FLUID_VOICE_ENVHOLD].coeff = 1.0f;
modenv_data[FLUID_VOICE_ENVHOLD].incr = 0.0f;
modenv_data[FLUID_VOICE_ENVHOLD].min = -1.0f;
modenv_data[FLUID_VOICE_ENVHOLD].max = 2.0f;
break;
case GEN_MODENVDECAY: /* SF 2.01 section 8.1.3 # 28 */
case GEN_MODENVSUSTAIN: /* SF 2.01 section 8.1.3 # 29 */
case GEN_KEYTOMODENVDECAY: /* SF 2.01 section 8.1.3 # 32 */
count = calculate_hold_decay_frames(GEN_MODENVDECAY, GEN_KEYTOMODENVDECAY, 1); /* 1 for decay */
y = 1.0f - 0.001f * GEN(GEN_MODENVSUSTAIN);
fluid_clip(y, 0.0f, 1.0f);
modenv_data[FLUID_VOICE_ENVDECAY].count = count;
modenv_data[FLUID_VOICE_ENVDECAY].coeff = 1.0f;
modenv_data[FLUID_VOICE_ENVDECAY].incr = count ? -1.0f / count : 0.0f;
modenv_data[FLUID_VOICE_ENVDECAY].min = y;
modenv_data[FLUID_VOICE_ENVDECAY].max = 2.0f;
break;
case GEN_MODENVRELEASE: /* SF 2.01 section 8.1.3 # 30 */
x = GEN(GEN_MODENVRELEASE);
fluid_clip(x, -12000.0f, 8000.0f);
count = 1 + NUM_FRAMES_RELEASE(x);
modenv_data[FLUID_VOICE_ENVRELEASE].count = count;
modenv_data[FLUID_VOICE_ENVRELEASE].coeff = 1.0f;
modenv_data[FLUID_VOICE_ENVRELEASE].incr = count ? -1.0f / count : 0.0;
modenv_data[FLUID_VOICE_ENVRELEASE].min = 0.0f;
modenv_data[FLUID_VOICE_ENVRELEASE].max = 2.0f;
break;
} /* switch gen */
}
/**
* fluid_voice_modulate
*
* In this implementation, I want to make sure that all controllers
* are event based: the parameter values of the DSP algorithm should
* only be updates when a controller event arrived and not at every
* iteration of the audio cycle (which would probably be feasible if
* the synth was made in silicon).
*
* The update is done in three steps:
*
* - first, we look for all the modulators that have the changed
* controller as a source. This will yield a list of generators that
* will be changed because of the controller event.
*
* - For every changed generator, calculate its new value. This is the
* sum of its original value plus the values of al the attached
* modulators.
*
* - For every changed generator, convert its value to the correct
* unit of the corresponding DSP parameter
* */
void Voice::modulate(bool _cc, int _ctrl)
{
// For our purposes in MuseScore, we don't need to be able to control all
// modulators in the release phase. In fact, we don't want these modulators to
// have an effect, since it can lead to 'volume bumps' for single note
// dynamics, when there is a sudden change from quiet to loud sounds.
// So, if the voice is in release phase, don't apply these modulators.
if (volenv_section == FLUID_VOICE_ENVRELEASE && _cc &&
(_ctrl == BREATH_MSB || _ctrl == FOOT_MSB || _ctrl == EXPRESSION_MSB))
return;
for (int i = 0; i < mod_count; i++) {
Mod* m = &mod[i];
/* step 1: find all the modulators that have the changed controller
* as input source.
*/
if (m->has_source(_cc, _ctrl)) {
int g = m->get_dest();
float modval = 0.0;
/* step 2: for every changed modulator, calculate the modulation
* value of its associated generator
*/
for (int k = 0; k < mod_count; k++) {
if (fluid_mod_has_dest(&mod[k], g)) {
modval += mod[k].get_value(channel, this);
}
}
gen[g].set_mod(modval);
/* step 3: now that we have the new value of the generator,
* recalculate the parameter values that are derived from the
* generator
*/
update_param(g);
}
}
}
/**
* fluid_voice_modulate_all
*
* Update all the modulators. This function is called after a
* ALL_CTRL_OFF MIDI message has been received (CC 121).
*
*/
void Voice::modulate_all()
{
/* Loop through all the modulators.
FIXME: we should loop through the set of generators instead of
the set of modulators. We risk to call 'fluid_voice_update_param'
several times for the same generator if several modulators have
that generator as destination. It's not an error, just a wast of
energy (think pollution, global warming, unhappy musicians, ...)
*/
for (int i = 0; i < mod_count; i++) {
Mod* m = &mod[i];
int g = m->get_dest();
float modval = 0.0;
/* Accumulate the modulation values of all the modulators with
* destination generator 'gen'
*/
for (int k = 0; k < mod_count; k++) {
if (fluid_mod_has_dest(&mod[k], g))
modval += mod[k].get_value(channel, this);
}
gen[g].set_mod(modval);
/* Update the parameter values that are depend on the generator
* 'gen'
*/
update_param(g);
}
}
/*
* fluid_voice_noteoff
*/
void Voice::noteoff()
{
if (channel && channel->sustained())
status = FLUID_VOICE_SUSTAINED;
else {
if (volenv_section == FLUID_VOICE_ENVATTACK) {
/* A voice is turned off during the attack section of the volume
* envelope. The attack section ramps up linearly with
* amplitude. The other sections use logarithmic scaling. Calculate new
* volenv_val to achieve equievalent amplitude during the release phase
* for seamless volume transition.
*/
if (volenv_val > 0) {
float lfo = modlfo_val * -modlfo_to_vol;
float ampl = volenv_val * pow (10.0, lfo / -200);
float env_value = - ((-200 * log (ampl) / log (10.0) - lfo) / 960.0 - 1);
fluid_clip (env_value, 0.0, 1.0);
volenv_val = env_value;
}
}
volenv_section = FLUID_VOICE_ENVRELEASE;
volenv_count = 0;
modenv_section = FLUID_VOICE_ENVRELEASE;
modenv_count = 0;
}
}
/*
* fluid_voice_kill_excl
*
* Percussion sounds can be mutually exclusive: for example, a 'closed
* hihat' sound will terminate an 'open hihat' sound ringing at the
* same time. This behaviour is modeled using 'exclusive classes',
* turning on a voice with an exclusive class other than 0 will kill
* all other voices having that exclusive class within the same preset
* or channel. fluid_voice_kill_excl gets called, when 'voice' is to
* be killed for that reason.
*/
void Voice::kill_excl()
{
if (!isPlaying())
return;
/* Turn off the exclusive class information for this voice,
so that it doesn't get killed twice
*/
gen_set(GEN_EXCLUSIVECLASS, 0);
/* If the voice is not yet in release state, put it into release state */
if (volenv_section != FLUID_VOICE_ENVRELEASE) {
volenv_section = FLUID_VOICE_ENVRELEASE;
volenv_count = 0;
modenv_section = FLUID_VOICE_ENVRELEASE;
modenv_count = 0;
}
/* Speed up the volume envelope */
/* The value was found through listening tests with hi-hat samples. */
gen_set(GEN_VOLENVRELEASE, -200);
update_param(GEN_VOLENVRELEASE);
/* Speed up the modulation envelope */
gen_set(GEN_MODENVRELEASE, -200);
update_param(GEN_MODENVRELEASE);
}
//---------------------------------------------------------
// off
// Turns off a voice, meaning that it is not processed
// anymore by the DSP loop.
//---------------------------------------------------------
void Voice::off()
{
chan = NO_CHANNEL;
volenv_section = FLUID_VOICE_ENVFINISHED;
volenv_count = 0;
modenv_section = FLUID_VOICE_ENVFINISHED;
modenv_count = 0;
status = FLUID_VOICE_OFF;
_fluid->freeVoice(this);
_cachedFrames = 0;
_initialCacheFrames = 0;
}
/*
* fluid_voice_add_mod
*
* Adds a modulator to the voice. "mode" indicates, what to do, if
* an identical modulator exists already.
*
* mode == FLUID_VOICE_ADD: Identical modulators on preset level are added
* mode == FLUID_VOICE_OVERWRITE: Identical modulators on instrument level are overwritten
* mode == FLUID_VOICE_DEFAULT: This is a default modulator, there can be no identical modulator.
* Don't check.
*/
void Voice::add_mod(const Mod* _mod, int mode)
{
/*
* Some soundfonts come with a huge number of non-standard
* controllers, because they have been designed for one particular
* sound card. Discard them, maybe print a warning.
*/
if (((_mod->flags1 & FLUID_MOD_CC) == 0)
&& ((_mod->src1 != 0) /* SF2.01 section 8.2.1: Constant value */
&& (_mod->src1 != 2) /* Note-on velocity */
&& (_mod->src1 != 3) /* Note-on key number */
&& (_mod->src1 != 10) /* Poly pressure */
&& (_mod->src1 != 13) /* Channel pressure */
&& (_mod->src1 != 14) /* Pitch wheel */
&& (_mod->src1 != 16))) { /* Pitch wheel sensitivity */
qDebug("Ignoring invalid controller, using non-CC source %i.", _mod->src1);
return;
}
if (mode == FLUID_VOICE_ADD) {
/* if identical modulator exists, add them */
for (int i = 0; i < mod_count; i++) {
if (test_identity(&mod[i], _mod)) {
//printf("Adding modulator...\n");
mod[i].amount += _mod->amount;
return;
}
}
}
else if (mode == FLUID_VOICE_OVERWRITE) {
/* if identical modulator exists, replace it (only the amount has to be changed) */
for (int i = 0; i < mod_count; i++) {
if (test_identity(&mod[i], _mod)) {
//printf("Replacing modulator...amount is %f\n",mod->amount);
mod[i].amount = _mod->amount;
return;
}
}
}
/* Add a new modulator (No existing modulator to add / overwrite).
Also, default modulators (FLUID_VOICE_DEFAULT) are added without
checking, if the same modulator already exists.
*/
if (mod_count < FLUID_NUM_MOD)
_mod->clone(&mod[mod_count++]);
}
/*
* fluid_voice_get_lower_boundary_for_attenuation
*
* Purpose:
*
* A lower boundary for the attenuation (as in 'the minimum
* attenuation of this voice, with volume pedals, modulators
* etc. resulting in minimum attenuation, cannot fall below x cB) is
* calculated. This has to be called during fluid_voice_init, after
* all modulators have been run on the voice once. Also,
* voice->attenuation has to be initialized.
*/
float Voice::get_lower_boundary_for_attenuation()
{
float possible_att_reduction_cB = 0;
for (int i = 0; i < mod_count; i++) {
Mod* m = &mod[i];
/* Modulator has attenuation as target and can change over time? */
if ((m->dest == GEN_ATTENUATION) && ((m->flags1 & FLUID_MOD_CC) || (m->flags2 & FLUID_MOD_CC))) {
float current_val = m->get_value(channel, this);
float v = fabs(m->amount);
if ((m->src1 == FLUID_MOD_PITCHWHEEL)
|| (m->flags1 & FLUID_MOD_BIPOLAR)
|| (m->flags2 & FLUID_MOD_BIPOLAR)
|| (m->amount < 0)) {
/* Can this modulator produce a negative contribution? */
v *= -1.0;
}
else {
/* No negative value possible. But still, the minimum contribution is 0. */
v = 0;
}
/* For example:
* - current_val=100
* - min_val=-4000
* - possible_att_reduction_cB += 4100
*/
if (current_val > v)
possible_att_reduction_cB += (current_val - v);
}
}
float lower_bound = attenuation - possible_att_reduction_cB;
/* SF2.01 specs do not allow negative attenuation */
if (lower_bound < 0)
lower_bound = 0;
return lower_bound;
}
/* Purpose:
*
* Make sure, that sample start / end point and loop points are in
* proper order. When starting up, calculate the initial phase.
*/
void Voice::check_sample_sanity()
{
int min_index_nonloop=(int) sample->start;
int max_index_nonloop=(int) sample->end;
/* make sure we have enough samples surrounding the loop */
int min_index_loop=(int) sample->start + FLUID_MIN_LOOP_PAD;
int max_index_loop=(int) sample->end - FLUID_MIN_LOOP_PAD;
fluid_check_fpe("voice_check_sample_sanity start");
if (!check_sample_sanity_flag)
return;
#if 0
printf("Sample from %i to %i\n", sample->start, sample->end);
printf("Sample loop from %i %i\n", sample->loopstart, sample->loopend);
printf("Playback from %i to %i\n", start, end);
printf("Playback loop from %i to %i\n", loopstart, loopend);
#endif
/* Keep the start point within the sample data */
if (start < min_index_nonloop)
start = min_index_nonloop;
else if (start > max_index_nonloop)
start = max_index_nonloop;
/* Keep the end point within the sample data */
if (end < min_index_nonloop)
end = min_index_nonloop;
else if (end > max_index_nonloop)
end = max_index_nonloop;
/* Keep start and end point in the right order */
if (start > end) {
int temp = start;
start = end;
end = temp;
}
/* Zero length? */
if (start == end) {
off();
return;
}
if ((SAMPLEMODE() == FLUID_LOOP_UNTIL_RELEASE) || (SAMPLEMODE() == FLUID_LOOP_DURING_RELEASE)) {
/* Keep the loop start point within the sample data */
if (loopstart < min_index_loop)
loopstart = min_index_loop;
else if (loopstart > max_index_loop)
loopstart = max_index_loop;
/* Keep the loop end point within the sample data */
if (loopend < min_index_loop)
loopend = min_index_loop;
else if (loopend > max_index_loop)
loopend = max_index_loop;
/* Keep loop start and end point in the right order */
if (loopstart > loopend){
int temp = loopstart;
loopstart = loopend;
loopend = temp;
}
/* Loop too short? Then don't loop. */
if (loopend < loopstart + FLUID_MIN_LOOP_SIZE)
gen[GEN_SAMPLEMODE].val = FLUID_UNLOOPED;
/* The loop points may have changed. Obtain a new estimate for the loop volume. */
/* Is the voice loop within the sample loop?
*/
if ((int)loopstart >= (int)sample->loopstart && (int)loopend <= (int)sample->loopend){
/* Is there a valid peak amplitude available for the loop? */
if (sample->amplitude_that_reaches_noise_floor_is_valid) {
amplitude_that_reaches_noise_floor_loop = sample->amplitude_that_reaches_noise_floor;
}
else
/* Worst case */
amplitude_that_reaches_noise_floor_loop = amplitude_that_reaches_noise_floor_nonloop;
}
} /* if sample mode is looped */
/* Run startup specific code (only once, when the voice is started) */
if (check_sample_sanity_flag & FLUID_SAMPLESANITY_STARTUP) {
if (max_index_loop - min_index_loop < FLUID_MIN_LOOP_SIZE){
if ((SAMPLEMODE() == FLUID_LOOP_UNTIL_RELEASE) || (SAMPLEMODE() == FLUID_LOOP_DURING_RELEASE))
gen[GEN_SAMPLEMODE].val = FLUID_UNLOOPED;
}
/* Set the initial phase of the voice (using the result from the
start offset modulators).
*/
phase.setInt(start);
} /* if startup */
/* Is this voice run in loop mode, or does it run straight to the
end of the waveform data?
*/
if (((SAMPLEMODE() == FLUID_LOOP_UNTIL_RELEASE) && (volenv_section < FLUID_VOICE_ENVRELEASE)) || (SAMPLEMODE() == FLUID_LOOP_DURING_RELEASE)) {
/* Yes, it will loop as soon as it reaches the loop point. In
* this case we must prevent, that the playback pointer (phase)
* happens to end up beyond the 2nd loop point, because the
* point has moved. The DSP algorithm is unable to cope with
* that situation. So if the phase is beyond the 2nd loop
* point, set it to the start of the loop. No way to avoid some
* noise here. Note: If the sample pointer ends up -before the
* first loop point- instead, then the DSP loop will just play
* the sample, enter the loop and proceed as expected => no
* actions required.
*/
int index_in_sample = phase.index();
if (index_in_sample >= loopend) {
/* FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Phase after 2nd loop point!"); */
phase.setInt(loopstart);
}
}
/* FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Sample from %i to %i, loop from %i to %i", voice->start, voice->end, voice->loopstart, voice->loopend); */
/* Sample sanity has been assured. Don't check again, until some
sample parameter is changed by modulation.
*/
check_sample_sanity_flag = 0;
fluid_check_fpe("voice_check_sample_sanity");
}
//---------------------------------------------------------
// set_param
//---------------------------------------------------------
void Voice::set_param(int g, float nrpn_value, int abs)
{
gen[g].nrpn = nrpn_value;
gen[g].flags = (abs)? GEN_ABS_NRPN : GEN_SET;
update_param(g);
}
/** If the peak volume during the loop is known, then the voice can
* be released earlier during the release phase. Otherwise, the
* voice will operate (inaudibly), until the envelope is at the
* nominal turnoff point. In many cases the loop volume is many dB
* below the maximum volume. For example, the loop volume for a
* typical acoustic piano is 20 dB below max. Taking that into
* account in the turn-off algorithm we can save 20 dB / 100 dB =>
* 1/5 of the total release time.
* So it's a good idea to call fluid_voice_optimize_sample
* on each sample once.
*/
/* - Scan the loop
* - determine the peak level
* - Calculate, what factor will make the loop inaudible
* - Store in sample
*/
void Sample::optimize()
{
Sample* s = this;
signed short peak_max = 0;
signed short peak_min = 0;
signed short peak;
float normalized_amplitude_during_loop;
double result;
/* ignore ROM and other(?) invalid samples */
if (!s->valid())
return;
if (!s->amplitude_that_reaches_noise_floor_is_valid) { /* Only once */
/* Scan the loop */
for (size_t i = s->loopstart; i < s->loopend; i++) {
signed short val = s->data[i];
if (val > peak_max)
peak_max = val;
else if (val < peak_min)
peak_min = val;
}
/* Determine the peak level */
if (peak_max > -peak_min)
peak = peak_max;
else
peak = -peak_min;
if (peak == 0) /* Avoid division by zero */
peak = 1;
/* Calculate what factor will make the loop inaudible
* For example: Take a peak of 3277 (10 % of 32768). The
* normalized amplitude is 0.1 (10 % of 32768). An amplitude
* factor of 0.0001 (as opposed to the default 0.00001) will
* drop this sample to the noise floor.
*/
/* 16 bits => 96+4=100 dB dynamic range => 0.00001 */
normalized_amplitude_during_loop = ((float)peak)/32768.;
result = FLUID_NOISE_FLOOR / normalized_amplitude_during_loop;
/* Store in sample */
s->amplitude_that_reaches_noise_floor = (double)result;
s->amplitude_that_reaches_noise_floor_is_valid = 1;
}
}
/* Purpose:
*
* - filters (applies a lowpass filter with variable cutoff frequency and quality factor)
* - mixes the processed sample to left and right output using the pan setting
* - sends the processed sample to chorus and reverb
*
* A couple of variables are used internally, their results are discarded:
* - dsp_phase_fractional: The fractional part of dsp_phase
* - dsp_coeff: A table of four coefficients, depending on the fractional phase.
* Used to interpolate between samples.
* - dsp_process_buffer: Holds the processed signal between stages
* - dsp_centernode: delay line for the IIR filter
* - dsp_hist1: same
* - dsp_hist2: same
*
*/
void Voice::effects(int startBufIdx, int count, float* out, float* reverb, float* chorus)
{
/* filter (implement the voice filter according to SoundFont standard) */
/* Check for denormal number (too close to zero). */
if (fabs (hist1) < 1e-20)
hist1 = 0.0f; /* FIXME JMG - Is this even needed? */
/* Two versions of the filter loop. One, while the filter is
* changing towards its new setting. The other, if the filter
* doesn't change.
*/
if (filter_coeff_incr_count > 0) {
/* Increment is added to each filter coefficient filter_coeff_incr_count times. */
for (int i = startBufIdx; i < startBufIdx + count; i++) {
/* The filter is implemented in Direct-II form. */
auto& dspValRef = dsp_buf[i];
float dsp_centernode = dspValRef - a1 * hist1 - a2 * hist2;
dspValRef = b02 * (dsp_centernode + hist2) + b1 * hist1;
hist2 = hist1;
hist1 = dsp_centernode;
if (filter_coeff_incr_count-- > 0) {
a1 += a1_incr;
a2 += a2_incr;
b02 += b02_incr;
b1 += b1_incr;
}
//code duplication is needed to optimize using std::vector::operator[]
float vv = dspValRef * amp_left;
*out++ += vv;
*reverb++ += vv * amp_reverb;
*chorus++ += vv * amp_chorus;
vv = dspValRef * amp_right;
*out++ += vv;
*reverb++ += vv * amp_reverb;
*chorus++ += vv * amp_chorus;
}
}
else { /* The filter parameters are constant. This is duplicated to save time. */
for (int i = startBufIdx; i < startBufIdx + count; i++) { // The filter is implemented in Direct-II form.
auto& dspValRef = dsp_buf[i];
float dsp_centernode = dspValRef - a1 * hist1 - a2 * hist2;
dspValRef = b02 * (dsp_centernode + hist2) + b1 * hist1;
hist2 = hist1;
hist1 = dsp_centernode;
//code duplication is needed to optimize using std::vector::operator[]
float vv = dspValRef * amp_left;
*out++ += vv;
*reverb++ += vv * amp_reverb;
*chorus++ += vv * amp_chorus;
vv = dspValRef * amp_right;
*out++ += vv;
*reverb++ += vv * amp_reverb;
*chorus++ += vv * amp_chorus;
}
}
}
}
↑ V1051 Consider checking for misprints. It's possible that the 'modlfo_dur' should be checked here.
↑ V1042 This file is marked with copyleft license, which requires you to open the derived source code.


Practical introduction into HTML5. Great examples, very easy to understand.
BacaPractical introduction into the very basics of CSS3. Great examples, very easy to understand. Less interesting if you've read Handcrafted CSS before.
Visit websitePractical introduction into the very basics of CSS3. Great examples, very easy to understand.
Visit websiteOne of the first books on Responsive Design, and I believe still one of the best i've read! Extremely practical, well explained and many techniques still work.
Visit websiteAnother very well written and extremely useful book. It pretty much set a new baseline for the projects I work on nowadays. I recommend reading Responsive Web Design first.
Visit websiteTo be honest, I haven't finished this book... No valid rating.
Visit websiteGreat Javascript reference, especially in the current days where everyone uses jQuery and tends to forget about "native" Javascript.
Visit websiteGreat book on CSS. Same author as the previous mentioned CSS for Webdesigners, and the book has the same qualities!
Visit websiteReally looking forward to this book! I'm a great fan of SASS and can't to read about in this book...
Visit websiteThought this book might be useful. Not very excited though....
Visit websiteThought this book might be useful. Not very excited though....
Visit websiteThought this book might be useful. Not very excited though....
Visit website


GOV.UK uses cookies to make the site simpler. Find out more about cookies
Start the default username and password login journey
Show the interaction complete page


Draw a snowflake outline using trigonometry functions
The starter program defines a Snowflake type. You will have to draw it.
Draw a circle in the Snowflake.draw() method using the ellipse() function with the data contained in the snowflake: x, y, innerRadius:
class Snowflake {
// configurable
float x;
float y;
float innerRadius;
...
void draw()
{
// get ready to draw
stroke(flakeColor);
strokeWeight(innerRadius/10);
noFill();
// draw the inner circle using the ellipse function
... you will have to call the ellipse() function here with the right parameters ...
}
Draw six long lines and six small lines around edge of the circle: To do this it will be easiest to use some trigonomery (sorry if you've not yet done this in maths!):
Think of the snowflake outline contained within various circles.
The points on the edges of the circles are based on the sin or cos functions multiplied by the radius of the circle you are thinking about...
You will need a loop something like this in the Snowflake.draw() method:
// draw the 6 long lines
for (int i = 0; i < 6; ++i) {
// work out where to draw the line
// who has done trigonometry in maths then?
float r = i * TWO_PI/6; // radians - need to use these for sin & cos to work properly, a full circle is TWO_PI radians
float s = sin(r);
float c = cos(r);
float x0 = ...x positon on inner snowflake circle (innerRadius)...
float y0 = ...y positon on inner snowflake circle (innerRadius)...
float x1 = ...x positon on outer snowflake circle (outerRadius)...
float y1 = ...y positon on outer snowflake circle (outerRadius is already stored)...
// draw the line
line(x0, y0, x1, y1);
}
This is not that hard if you can do the medium challenge. Just some more trigonometry with slightly different angles.


Hi,
I'm currently working on a plugin which adds all current platoon members which are online to the comcenter. Of course sorted by groups.
It is based on the dicefriends plugin and although it is working, it only does so when I add an alert to it.
I can't get it to work without the alert. Maybe somebody has an idea ord figures it out.
The development link to the plugin is:
http://labs.web-wack.at/platoonFriends.js
Regards,
Horfic
BrainFooLong
Administrator
It's a simple "problem" but a bit harder to fix.
Your problem is that you use some iterations, and in it you call functions/methods.
And thats the point with the problem - Javascript is ASYNC, so it could happen that your iteration is finished but some method calls in it are still in queue in a undefined order.
Thats also the reason why most things in javascript apis like jQuery work with callbacks.
When you call "alert" on every iteration step, the script stops at this point but already queued method calls still be processed.
morre599
I was inspired by this script and made it work. It is a litle buggy but it works. var PlatoonFriends = {
updateInterval : 60*5,
init : function () {
var friendListSurface = $S("comcenter-surface-friends");
friendListSurface.oldUpdate = friendListSurface.update;
friendListSurface.update = function(itemState, opts) { var ret = this.oldUpdate(itemState, opts); PlatoonFriends.update(); return ret;}
friendListSurface.oldRefresh = friendListSurface.refresh;
friendListSurface.refresh = function() { var ret = this.oldRefresh(); PlatoonFriends.update(); return ret;}
update : function() {
var platoons = Surface.globalContext.userContext.platoons;
var platoonsObj = [];
var playerList = [];
for (var i = 0; i 0) {
// if yes, clear it
platoonContainer.empty();
} else {
// if no, create it
$('#comcenter-surface-friends #comcenterOnlineFriends').before(
$('').attr('id', 'comcenterPlatoonFriends-'+id)
);
for(var i in members) {
var member = members[i];
var user = member.user;
// if player is member of the platoon (not only invited) and in a PC game
//if(member.membershipLevel >= 4 && user.presence.isPlaying && user.presence.platform == 1 )
if(member.membershipLevel >= 4 && user.presence.isOnline && json.context.me.userId != user.userId) {
var player =
{
name : user.username,
userId : user.userId,
personaId : member.personaId,
userAvatar : user.gravatarMd5,
serverGuid : user.presence.serverGuid,
serverName : user.presence.serverName
}


public class Kern
extends java.lang.Object
| Constructor and Description |
|---|
Kern(int[] firstGlyphCodes,
int[] secondGlyphCodes,
UnicodeRange[] firstUnicodeRanges,
UnicodeRange[] secondUnicodeRanges,
float adjustValue)
Creates a Kern object with the given glyph arrays
and kerning value.
|
| Modifier and Type | Method and Description |
|---|---|
float |
getAdjustValue()
Returns the kerning adjustment value for this kerning entry (a positive
value means the space between characters should decrease).
|
boolean |
matchesFirstGlyph(int glyphCode,
char glyphUnicode)
Returns true if the specified glyph is one of the glyphs considered
as first by this kerning entry.
|
boolean |
matchesFirstGlyph(int glyphCode,
java.lang.String glyphUnicode)
Returns true if the specified glyph is one of the glyphs considered
as first by this kerning entry.
|
boolean |
matchesSecondGlyph(int glyphCode,
char glyphUnicode)
Returns true if the specified glyph is one of the glyphs considered
as second by this kerning entry.
|
boolean |
matchesSecondGlyph(int glyphCode,
java.lang.String glyphUnicode)
Returns true if the specified glyph is one of the glyphs considered
as second by this kerning entry.
|
public Kern(int[] firstGlyphCodes, int[] secondGlyphCodes, UnicodeRange[] firstUnicodeRanges, UnicodeRange[] secondUnicodeRanges, float adjustValue)
firstGlyphCodes
- An array of glyph codes that are part of the first
set of glyphs in this kerning entry.secondGlyphCodes
- An array of glyph codes that are part of the
second set of glyphs in this kerning entry.firstUnicodeRanges
- An array of unicode ranges that are part of the
first set of glyphs in this kerning entry.secondUnicodeRanges
- An array of unicode ranges that are part of
the second set of glyphs in this kerning entry.adjustValue
- The kerning adjustment (positive value means the space
between glyphs should decrease).public boolean matchesFirstGlyph(int glyphCode, java.lang.String glyphUnicode)
glyphCode
- The id of the glyph to test.glyphUnicode
- The unicode value of the glyph to test.public boolean matchesFirstGlyph(int glyphCode, char glyphUnicode)
glyphCode
- The id of the glyph to test.glyphUnicode
- The unicode value of the glyph to test.public boolean matchesSecondGlyph(int glyphCode, java.lang.String glyphUnicode)
glyphCode
- The id of the glyph to test.glyphUnicode
- The unicode value of the glyph to test.public boolean matchesSecondGlyph(int glyphCode, char glyphUnicode)
glyphCode
- The id of the glyph to test.glyphUnicode
- The unicode value of the glyph to test.public float getAdjustValue()
Copyright © 2022 Apache Software Foundation. All Rights Reserved.


About Us
More...
Contacts
Pop-up menu with HTML & CSS Only |
Back to all tasks
NO WASTE
Recycling Station