PageRenderTime 59ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/fmplayer.cpp

https://gitlab.com/qliss3d/pkg-debian-full
C++ | 655 lines | 499 code | 121 blank | 35 comment | 107 complexity | 4b7c19ed03ca7c63b457bbce117d43f0 MD5 | raw file
  1. /**************************************************************************
  2. fmplayer.cpp - all the FMPlayer-API
  3. -------------------
  4. begin : September 20th 2002
  5. copyright : (C) 2002-2003 by Daniel Gruen
  6. email : daniel_gruen@web.de
  7. ***************************************************************************/
  8. /***************************************************************************
  9. * *
  10. * This program is free software; you can redistribute it and/or modify *
  11. * it under the terms of the GNU General Public License as published by *
  12. * the Free Software Foundation; either version 2 of the License, or *
  13. * (at your option) any later version. *
  14. * *
  15. ***************************************************************************/
  16. // this is a slim and special fms version for qliss3d
  17. // please use the original version from http://sourceforge.net/projects/fmsynth
  18. // if you want to do anything on it
  19. #include "include/fmplayer.h"
  20. #include <cmath>
  21. #ifdef FMS_WORKS
  22. #include <cstdlib>
  23. #include <cstring>
  24. #include <iostream>
  25. #include <unistd.h>
  26. #include <fcntl.h>
  27. #include <sys/ioctl.h>
  28. #include <sys/soundcard.h>
  29. #include "include/fmval.h"
  30. #include "include/version.h"
  31. using namespace std;
  32. int dspfd = 0;
  33. void writeSoundByte(unsigned char * byte, PlayMode mode) {
  34. ssize_t r;
  35. //cout << int(byte) << endl;
  36. if(mode == DSP)
  37. r = write(dspfd, byte, 1);
  38. if(mode != DSP)
  39. return;
  40. while ((r = write(dspfd, byte, 1)) < 1) {
  41. if (r == -1)
  42. return;
  43. }
  44. }
  45. /*----------------------------------------------------------------*/
  46. FMPlayer::FMPlayer() {
  47. if(debug_level>1)
  48. cout << "FMPlayer::FMPlayer called" << endl;
  49. first = new FMChannel(this);
  50. channel = first;
  51. syncPointer();
  52. rate = D_SAMPRATE;
  53. mode = DSP;
  54. }
  55. FMPlayer::~FMPlayer() {
  56. if(debug_level>1)
  57. cout << "FMPlayer::~FMPlayer called" << endl;
  58. delete first;
  59. if(debug_level>1)
  60. cout << "FMPlayer::~FMPlayer finished" << endl;
  61. }
  62. void FMPlayer::nextSound() {
  63. if(debug_level>1)
  64. cout << "FMPlayer::nextSound called" << endl;
  65. channel->nextSound();
  66. syncPointer();
  67. }
  68. void FMPlayer::setRate(int drate) {
  69. if(debug_level>1)
  70. cout << "FMPlayer::setRate called" << endl;
  71. rate = drate;
  72. }
  73. int FMPlayer::getRate() const {
  74. return rate;
  75. }
  76. void FMPlayer::openFiles() {
  77. if(debug_level>1)
  78. cout << "FMPlayer::openFiles called" << endl;
  79. try{
  80. first->openFiles();
  81. }
  82. catch(...){
  83. cout << "caught error in FMPlayer::openFiles" << endl;
  84. throw;
  85. }
  86. }
  87. void FMPlayer::compute() {
  88. if(debug_level>1)
  89. cout << "FMPlayer::compute called" << endl;
  90. first->compute();
  91. }
  92. void FMPlayer::syncPointer() {
  93. if(debug_level>1)
  94. cout << "FMPlayer::syncPointer called" << endl;
  95. package = channel->package;
  96. sound = channel->sound;
  97. }
  98. void FMPlayer::play() {
  99. try{
  100. if(debug_level>1)
  101. cout << "FMPlayer::play called" << endl;
  102. openFiles();
  103. compute();
  104. playInit();
  105. while(first->ptr)
  106. playVal();
  107. playCleanup();
  108. }
  109. catch(int x){
  110. if(x>0) // wenn's eine Fehlermeldung ist
  111. throw;
  112. }
  113. }
  114. void FMPlayer::playInit() {
  115. if(debug_level>1)
  116. cout << "FMPlayer::playInit called" << endl;
  117. int format = AFMT_U8;
  118. int chan = 0;
  119. first->pointerReset();
  120. try{
  121. if(mode == DSP && !dspfd){
  122. if(debug_level>1)
  123. cout << "going to open and initialize /dev/dsp" << endl;
  124. if((dspfd = open("/dev/dsp", O_WRONLY)) == -1) {
  125. mode = NONE;
  126. dspfd = 0;
  127. if(debug_level)
  128. cout << "error opening /dev/dsp: reset PlayMode and dsp-fd" << endl;
  129. throw DSP_OPEN_ERR;
  130. return;
  131. }
  132. if(ioctl(dspfd, SNDCTL_DSP_STEREO, &chan) == -1) {
  133. mode = NONE;
  134. throw DSP_CHAN_ERR;
  135. return;
  136. }
  137. if(ioctl(dspfd, SNDCTL_DSP_SETFMT, &format) == -1) {
  138. mode = NONE;
  139. throw DSP_SFMT_ERR;
  140. return;
  141. }
  142. if(ioctl(dspfd, SNDCTL_DSP_SPEED, &rate) == -1) {
  143. mode = NONE;
  144. throw DSP_RATE_ERR;
  145. return;
  146. }
  147. if(debug_level)
  148. cout << "opened /dev/dsp successfully!" << endl;
  149. }
  150. else if(mode == NONE){
  151. return;
  152. }
  153. else{
  154. if(debug_level)
  155. cout << "PlayMode " << mode << " not implemented!" << endl;
  156. throw PLY_MODE_ERR;
  157. return;
  158. }
  159. }
  160. catch(...){
  161. throw;
  162. }
  163. if(debug_level>1)
  164. cout << "FMPlayer::playInit finished" << endl;
  165. }
  166. void FMPlayer::playVal(){
  167. unsigned char buff[1];
  168. buff[0] = int(*first->ptr);
  169. writeSoundByte(buff, mode);
  170. first->ptrInc();
  171. }
  172. void FMPlayer::playCleanup() {
  173. if(debug_level>1)
  174. cout << "FMPlayer::playCleanup called" << endl;
  175. if(mode == DSP){
  176. if(ioctl(dspfd, SNDCTL_DSP_SYNC) == -1) {
  177. throw DSP_SYNC_ERR;
  178. }
  179. close(dspfd); dspfd = 0;
  180. }
  181. }
  182. /*----------------------------------------------------------------*/
  183. FMChannel::FMChannel(FMPlayer *parentPlayer) {
  184. if(debug_level>1)
  185. cout << "FMChannel::FMChannel called" << endl;
  186. player = parentPlayer;
  187. first = new FMPackage(this);
  188. package = first;
  189. syncPointer();
  190. ptr = 0;
  191. dr = 0;
  192. }
  193. FMChannel::~FMChannel(){
  194. if(debug_level>1)
  195. cout << "FMChannel::~FMChannel called" << endl;
  196. delete first;
  197. if(debug_level>1)
  198. cout << "FMChannel::~FMChannel finished" << endl;
  199. }
  200. void FMChannel::nextSound() {
  201. if(debug_level>1)
  202. cout << "FMChannel::nextSound called" << endl;
  203. package->nextSound();
  204. syncPointer();
  205. }
  206. void FMChannel::openFiles() {
  207. if(debug_level>1)
  208. cout << "FMChannel::openFiles called" << endl;
  209. try{
  210. first->openFiles();
  211. }
  212. catch(...){
  213. cout << "catch error in FMChannel::openFiles" << endl;
  214. throw;
  215. }
  216. }
  217. void FMChannel::compute() {
  218. if(debug_level>1)
  219. cout << "FMChannel::compute called" << endl;
  220. package = first;
  221. while(package){
  222. package->compute();
  223. package = 0;
  224. }
  225. ptr = first->values;
  226. package = first;
  227. dr = 0;
  228. }
  229. void FMChannel::syncPointer() {
  230. if(debug_level>1)
  231. cout << "FMChannel::syncPointer called" << endl;
  232. if(package)
  233. sound = package->sound;
  234. if(debug_level>1)
  235. cout << "FMChannel::syncPointer finished" << endl;
  236. }
  237. void FMChannel::ptrInc() {
  238. if(ptr){
  239. ptr++;
  240. i++;
  241. if(ptr >= package->values + package->getRval()){
  242. ptr = package->values;
  243. }
  244. if(i >= package->getTime() * player->getRate() * package->getRepeat()){
  245. // channel repeat problematisch!
  246. ptr = 0;
  247. }
  248. }
  249. }
  250. void FMChannel::pointerReset() {
  251. if(debug_level>1)
  252. cout << "FMChannel::pointerReset called" << endl;
  253. package = first;
  254. ptr = package->values;
  255. i = 0;
  256. if(debug_level>1)
  257. cout << "FMChannel::pointerReset finished" << endl;
  258. }
  259. /*----------------------------------------------------------------*/
  260. FMPackage::FMPackage(FMChannel *parentChannel){
  261. if(debug_level>1)
  262. cout << "FMPackage::FMPackage called" << endl;
  263. channel = parentChannel;
  264. tvol = 0.0; // have to do this before FMSoundfile::FMSoundfile(this)
  265. sound = new FMSoundfile(this);
  266. first = sound;
  267. time = 1.0;
  268. vol = 1.0;
  269. repeat = 1.0;
  270. rval = 0;
  271. values = 0;
  272. comp_lock=0;
  273. }
  274. FMPackage::~FMPackage() {
  275. if(debug_level>1)
  276. cout << "FMPackage::~FMPackage called" << endl;
  277. delete first;
  278. if(values)
  279. delete []values;
  280. if(debug_level>1)
  281. cout << "FMPackage::~FMPackage finished" << endl;
  282. }
  283. void FMPackage::nextSound() {
  284. if(debug_level>1)
  285. cout << "FMPackage::nextSound called" << endl;
  286. if(!sound->next){
  287. sound->next = new FMSoundfile(this);
  288. comp_lock=0;
  289. }
  290. sound = sound->next;
  291. }
  292. float FMPackage::getTime() const {
  293. return time;
  294. }
  295. void FMPackage::setTime(float dtime) {
  296. if(debug_level>1)
  297. cout << "FMPackage::setTime called" << endl;
  298. time = dtime; compLockAll();
  299. }
  300. float FMPackage::getVolume() const {
  301. if(debug_level>1)
  302. cout << "FMPackage::getVolume called" << endl;
  303. return vol;
  304. }
  305. void FMPackage::setVolume(float dvol) {
  306. if(debug_level>1)
  307. cout << "FMPackage::setVolume called" << endl;
  308. vol = dvol; comp_lock=0;
  309. }
  310. int FMPackage::getRval() const {
  311. return rval;
  312. }
  313. float FMPackage::getRepeat() const {
  314. return repeat;
  315. }
  316. void FMPackage::setTVol(float dtvol) {
  317. if(debug_level>1)
  318. cout << "FMPackage::setTVol called" << endl;
  319. tvol = dtvol;
  320. }
  321. float FMPackage::getTVol() const {
  322. return tvol;
  323. }
  324. void FMPackage::setRepeat(float drepeat) {
  325. if(debug_level>1)
  326. cout << "FMPackage::setRepeat called" << endl;
  327. repeat = drepeat;
  328. }
  329. void FMPackage::volumeChanged(float oldv, float newv){
  330. if(debug_level>1)
  331. cout << "FMPackage::volumeChanged called" << endl << "Volume changed: " << tvol << " - ";
  332. tvol += newv - oldv;
  333. if(debug_level>1)
  334. cout << tvol << endl;
  335. comp_lock=0;
  336. }
  337. void FMPackage::openFiles() {
  338. if(debug_level>1)
  339. cout << "FMPackage::openFiles called" << endl;
  340. try{
  341. FMSoundfile * tmpsound = first;
  342. while(tmpsound){
  343. if(!tmpsound->openLock())
  344. tmpsound->openFile();
  345. tmpsound = tmpsound->next;
  346. if(debug_level>1)
  347. cout << "opening of one file finished" << endl;
  348. }
  349. if(debug_level)
  350. cout << "opening of all files in package finished" << endl;
  351. }
  352. catch(...){
  353. cout << "caught error in FMPackage::openFiles" << endl;
  354. throw;
  355. }
  356. }
  357. void FMPackage::compute() {
  358. if(debug_level>1)
  359. cout << "FMPackage::compute called" << endl;
  360. if(comp_lock){
  361. FMSoundfile * tmp = first;
  362. bool ac = 1;
  363. while(tmp){
  364. ac = ac && tmp->compLock();
  365. tmp = tmp->next;
  366. }
  367. if(ac){
  368. if(debug_level)
  369. cout << "already computed" << endl;
  370. return;
  371. }
  372. }
  373. if(values){
  374. if(debug_level)
  375. cout << "recomputing package" << endl;
  376. delete []values;
  377. }
  378. // first, how many values do we need?
  379. rval = 1;
  380. //int numsounds = 0;
  381. FMSoundfile *tmpsound = first;
  382. while(tmpsound){
  383. //numsounds++;
  384. tmpsound->compute();
  385. tmpsound->setAtime(0.0);
  386. //tmpsound->setVolume(tmpsound->getVolume() / tvol, 0);
  387. // don't set total volume, that's the reason for 0
  388. rval = int(kgv(rval, tmpsound->rval()));
  389. tmpsound = tmpsound->next;
  390. }
  391. if(rval > channel->player->getRate() * time || rval < 0)
  392. rval = int(channel->player->getRate() * time);
  393. // ok, so we'll make a new value array
  394. if(debug_level>1)
  395. cout << rval << " values will be computed in package" << endl;
  396. values = new float[rval];
  397. ptr = values;
  398. if(debug_level>1)
  399. cout << "values starting @ " << ptr << endl;
  400. // and now, we'll actually compute the values
  401. while(ptr < values+rval){
  402. *ptr = 0.0;
  403. tmpsound = first;
  404. while(tmpsound){
  405. *ptr = *ptr + tmpsound->value();
  406. //if(tmpsound->ffreq)
  407. // tmpsound->setFreq(tmpsound->ffreq->HFValue());
  408. tmpsound = tmpsound->next;
  409. }
  410. ptr++;
  411. }
  412. comp_lock=1;
  413. if(debug_level>1)
  414. cout << "FMPackage::compute finished after computing" << endl;
  415. }
  416. void FMPackage::compLockAll(){
  417. }
  418. /*----------------------------------------------------------------*/
  419. FMFile::FMFile(FMPackage *parentPackage){
  420. if(debug_level>1)
  421. cout << "FMFile::FMFile called" << endl;
  422. package = parentPackage;
  423. freq = 1;
  424. atime = 0.0;
  425. open_lock = 0;
  426. volume = 1.0;
  427. }
  428. FMFile::~FMFile(){
  429. }
  430. bool FMFile::openLock(){
  431. if(debug_level>1)
  432. cout << "FMFile::openLock called" << endl;
  433. return open_lock;
  434. }
  435. bool FMFile::compLock(){
  436. if(debug_level>1)
  437. cout << "FMFile::compLock called" << endl;
  438. return 1;
  439. }
  440. void FMFile::compute(){
  441. if(debug_level>1)
  442. cout << "FMFile::compute called" << endl;
  443. }
  444. void FMFile::setFreq(float dfreq) {
  445. freq = dfreq;
  446. package->compLockAll();
  447. }
  448. void FMFile::setVolume(float dvolume, bool setptvol){
  449. if(debug_level>1)
  450. cout << "FMFile::setVolume called" << endl;
  451. if(setptvol){
  452. if(debug_level>1)
  453. cout << "changing total volume (" << volume << ", " << dvolume << ")" << endl;
  454. package->volumeChanged(volume, dvolume);
  455. }
  456. volume=dvolume;
  457. package->compLockAll();
  458. }
  459. float FMFile::getVolume() const {
  460. if(debug_level>1)
  461. cout << "FMFile::getVolume called" << endl;
  462. return volume;
  463. }
  464. void FMFile::setAtime(float datime) {
  465. if(debug_level>1)
  466. cout << "FMFile::setAtime called" << endl;
  467. atime = datime; /*should there be a comp_lock=0 here?*/
  468. }
  469. void FMFile::incAtime() {
  470. atime = fmod((atime + vtl[getVlen()-1].getTime() * freq / package->channel->player->getRate()),
  471. vtl[getVlen()-1].getTime());
  472. }
  473. void FMFile::openFile() {
  474. if(debug_level)
  475. cout << "FMFile::openFile called" << endl;
  476. try{
  477. init();
  478. }
  479. catch(...){
  480. throw;
  481. open_lock=0;
  482. }
  483. }
  484. float FMFile::value(bool count_on){
  485. float avalue = fmval(this, atime);
  486. if(count_on)
  487. incAtime();
  488. return avalue;
  489. }
  490. int FMFile::rval(){
  491. if(debug_level>1)
  492. cout << "FMFile::rval called" << endl;
  493. int drval = 1;
  494. drval = int(kgv(drval,package->channel->player->getRate() / freq));
  495. if(drval < 0.0 || drval > package->channel->player->getRate() * package->getTime())
  496. drval = int(package->channel->player->getRate() * package->getTime());
  497. return drval;
  498. }
  499. /*----------------------------------------------------------------*/
  500. FMSoundfile::FMSoundfile(FMPackage *parentPackage) : FMFile(parentPackage){
  501. if(debug_level>1)
  502. cout << "FMSoundfile::FMSoundfile called" << endl;
  503. next = 0;
  504. freq = 441.0;
  505. package->volumeChanged(0.0, 1.0);
  506. }
  507. FMSoundfile::~FMSoundfile(){
  508. if(debug_level>1)
  509. cout << "FMSoundfile::~FMSoundfile called" << endl;
  510. if(next)
  511. delete next;
  512. if(debug_level>1)
  513. cout << "FMSoundfile::~FMSoundfile finished" << endl;
  514. }
  515. float FMSoundfile::value(bool count_on){
  516. return FMFile::value(count_on) * (volume/package->getTVol());
  517. }
  518. /*----------------------------------------------------------------*/
  519. #endif
  520. float ggt(float a, float b) {
  521. if(a < 0)
  522. a = a * -1;
  523. if(b < 0)
  524. b = b * -1;
  525. if(b>a)
  526. return ggt(b, a);
  527. if(b!=0)
  528. return ggt(b, fmod(a, b));
  529. else
  530. return a;
  531. }
  532. float kgv(float a, float b) {
  533. return a*b/ggt(a, b);
  534. }