wavtool.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <sndfile.h>
  4. #include <speex/speex_echo.h>
  5. #include <speex/speex_preprocess.h>
  6. #include <speex/speex_resampler.h>
  7. #include "wavtool.h"
  8. #define AGC_DEFAULT_TARGET 8000
  9. #define AGC_DEFAULT_MAX_GAIN 12
  10. #define AGC_DEFAULT_DECREMENT -60
  11. WavTool::WavTool(){}
  12. SpeexPreprocessState* preproc_create(int samplerate)
  13. {
  14. SpeexPreprocessState* preproc = speex_preprocess_state_init(128, samplerate);
  15. // Enable AGC
  16. int val = 1;
  17. speex_preprocess_ctl(preproc, SPEEX_PREPROCESS_SET_AGC, &val);
  18. // Disable other
  19. val = 0;
  20. speex_preprocess_ctl(preproc, SPEEX_PREPROCESS_SET_DENOISE, &val);
  21. speex_preprocess_ctl(preproc, SPEEX_PREPROCESS_SET_DEREVERB, &val);
  22. speex_preprocess_ctl(preproc, SPEEX_PREPROCESS_SET_VAD, &val);
  23. val = AGC_DEFAULT_TARGET; // 8000 ~24% -- Default: 8000 ~24%
  24. speex_preprocess_ctl(preproc, SPEEX_PREPROCESS_SET_AGC_TARGET, &val);
  25. val = AGC_DEFAULT_MAX_GAIN; // +12dB -- Default 30dB
  26. speex_preprocess_ctl(preproc, SPEEX_PREPROCESS_SET_AGC_MAX_GAIN, &val);
  27. val = AGC_DEFAULT_DECREMENT; // -60dB per second -- Default -40dB
  28. speex_preprocess_ctl(preproc, SPEEX_PREPROCESS_SET_AGC_DECREMENT, &val);
  29. return preproc;
  30. }
  31. void WavTool::addNote(const char* infilename, float start,float length)
  32. {
  33. SF_INFO info;
  34. memset(&info,0,sizeof(info));
  35. SNDFILE* infile = sf_open(infilename,SFM_READ,&info);
  36. SpeexPreprocessState* preproc = preproc_create(info.samplerate);
  37. SpeexResamplerState *resampler = nullptr;
  38. wavdata* ret=new wavdata;
  39. ret->start=start;
  40. ret->length=length;
  41. int err=0;
  42. if(info.samplerate != _outputRate)
  43. resampler = speex_resampler_init(1, info.samplerate, _outputRate, 10, &err);
  44. //info.samplerate = output_rate;
  45. //SNDFILE* outfile = sf_open(outfilename,SFM_WRITE,&info);
  46. short data[128];
  47. short data2[1024];
  48. //store wav data
  49. while(1)
  50. {
  51. int count = sf_read_short(infile,data,128);
  52. speex_preprocess_run(preproc, data);
  53. for(int i=0;i<128;i++) data[i]*=0.9;
  54. int data2_length = 1024;
  55. if(resampler) {
  56. speex_resampler_process_int(resampler,0,data,(spx_uint32_t*)&count,data2,(spx_uint32_t*)&data2_length);
  57. for(int i=0;i<data2_length;i++) ret->data.push_back(data2[i]*1.0/32768);
  58. }
  59. if(count<128) break;
  60. }
  61. speex_preprocess_state_destroy(preproc);
  62. sf_close(infile);
  63. if(resampler) speex_resampler_destroy(resampler);
  64. _notes.push_back(ret);
  65. }
  66. void WavTool::mix()
  67. {
  68. float songLength = _notes[_notes.size()-1]->start + _notes[_notes.size()-1]->length;
  69. _outdataLength = _outputRate*songLength;
  70. _outdata = new float[_outdataLength];
  71. for(int i=0;i<(int)_notes.size();i++)
  72. {
  73. float start = _notes[i]->start;
  74. float end = start+_notes[i]->length;
  75. int startix = _outputRate*start;
  76. int endix = _outputRate*end;
  77. int count = endix-startix;
  78. //fprintf(stderr,"%i %i\n",startix,endix);
  79. for(int j=0;j<count;j++)
  80. {
  81. int index = j+startix;
  82. if(index>0 && index<_outdataLength && j<_notes[i]->data.size()) _outdata[index]+=_notes[i]->data[j];
  83. }
  84. }
  85. SF_INFO info;
  86. memset(&info,0,sizeof(info));
  87. info.channels=1;
  88. info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
  89. info.samplerate = _outputRate;
  90. SNDFILE* sf= sf_open("/tmp/wavtool.wav",SFM_WRITE,&info);
  91. sf_write_float(sf,_outdata,_outdataLength);
  92. sf_close(sf);
  93. //fprintf(stderr,"songLength %f\n",songLength);
  94. }
  95. void WavTool::clear()
  96. {
  97. _notes.clear();
  98. //TODO: delete memory
  99. }