Advertisement
feos

GapFix

Apr 27th, 2018
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.50 KB | None | 0 0
  1. /*
  2.  * Written by Ilari.
  3.  * Purpose: fix crackling sounds in Dolphin wav dumps.
  4.  * Usage: "gapfix infile.wav outfile wav"
  5.  * Note: compile with 44-byte wav header in mind (that Dolphin uses).
  6. */
  7.  
  8. #include <iostream>
  9. #include <cstdint>
  10. #include <fstream>
  11.  
  12. #define BLOCKSAMPLES 8
  13.  
  14. const double factor = 1000;
  15. const unsigned HEADERSIZE = 44; // Adjust this!
  16. const unsigned blocktype_nonzero = 0;
  17. const unsigned blocktype_zero = 1;
  18. const unsigned blocktype_gap = 2;
  19. const unsigned blocktype_eof = 3;
  20. const unsigned blocktype_sof = 4;
  21.  
  22. struct sample
  23. {
  24.     sample() { l = 0; r = 0; }
  25.     void read(char* buf)
  26.     {
  27.         l = ((unsigned char*)buf)[0] | ((unsigned short)((unsigned char*)buf)[1] << 8);
  28.         r = ((unsigned char*)buf)[2] | ((unsigned short)((unsigned char*)buf)[3] << 8);
  29.     }
  30.     void write(char* buf)
  31.     {
  32.         buf[0] = l;
  33.         buf[1] = l >> 8;
  34.         buf[2] = r;
  35.         buf[3] = r >> 8;
  36.     }
  37.     bool iszero() { return (l == 0 && r == 0); }
  38. private:
  39.     short l, r;
  40. };
  41.  
  42. struct block
  43. {
  44.     unsigned type;
  45.     sample samples[BLOCKSAMPLES];
  46. };
  47.  
  48. block readblock(std::istream& s)
  49. {
  50.     block b;
  51.     char buffer[4 * BLOCKSAMPLES];
  52.     s.read(buffer, 4 * BLOCKSAMPLES);
  53.     if(!s) {
  54.         b.type = blocktype_eof;
  55.         return b;
  56.     }
  57.     bool nz = false;
  58.     for(unsigned i = 0; i < BLOCKSAMPLES; i++) {
  59.         b.samples[i].read(buffer + 4 * i);
  60.         nz = nz || !b.samples[i].iszero();
  61.     }
  62.     b.type = nz ? blocktype_nonzero : blocktype_zero;
  63.     return b;
  64. }
  65.  
  66. struct block_filter
  67. {
  68.     block_filter(std::istream& _s)
  69.         : s(_s)
  70.     {
  71.         r[0].type = blocktype_sof;
  72.         r[1] = readblock(s);
  73.         r[2] = readblock(s);
  74.         ptr = 1;
  75.     }
  76.     block get()
  77.     {
  78.         block b = r[ptr];
  79.         //If zero block is surrounded by nonzero blocks, it becomes gap block.
  80.         unsigned ptrp = ptr - 1;
  81.         unsigned ptrn = ptr + 1;
  82.         if(ptrp > 2) ptrp = 2;
  83.         if(ptrn > 2) ptrn = 0;
  84.         if(r[ptrp].type == blocktype_nonzero && r[ptr].type == blocktype_zero && r[ptrn].type ==
  85.             blocktype_nonzero)
  86.             b.type = blocktype_gap;
  87.         ptr = ptrn;
  88.         r[ptrp] = readblock(s);
  89.         return b;
  90.     }
  91. private:
  92.     std::istream& s;
  93.     block r[3];
  94.     unsigned ptr;
  95. };
  96.  
  97. int main(int argc, char** argv)
  98. {
  99.     char header[HEADERSIZE];
  100.     std::ifstream in(argv[1], std::ios::binary);
  101.     std::ofstream out(argv[2], std::ios::binary);
  102.     in.read(header, HEADERSIZE);
  103.     out.write(header, HEADERSIZE);
  104.     block_filter bf(in);
  105.     uint64_t lag = 0;
  106.     uint64_t maxlag = 0;
  107.     uint64_t bytes = 0;
  108.     double counter = 0;
  109.     uint64_t gaps = 0;
  110.     while(true) {
  111.         block b = bf.get();
  112.         if(b.type == blocktype_eof)
  113.             break;
  114.         else if(b.type == blocktype_gap) {
  115.             gaps++;
  116.             lag += BLOCKSAMPLES;
  117.             if(lag > maxlag)
  118.                 maxlag = lag;
  119.         } else {
  120.             char buffer2[8 * BLOCKSAMPLES];
  121.             size_t buf2use = 0;
  122.             //Block to process.
  123.             for(unsigned i = 0; i < BLOCKSAMPLES; i++) {
  124.                 double increment = lag / factor;
  125.                 counter += increment;
  126.                 if(counter > 1 && lag) {
  127.                     b.samples[i].write(buffer2 + buf2use);
  128.                     b.samples[i].write(buffer2 + buf2use + 4);
  129.                     buf2use += 8;
  130.                     counter--;
  131.                     lag--;
  132.                 } else {
  133.                     b.samples[i].write(buffer2 + buf2use);
  134.                     buf2use += 4;
  135.                 }
  136.             }
  137.             out.write(buffer2, buf2use);
  138.         }
  139.         bytes += 4 * BLOCKSAMPLES;
  140.         if(bytes % 1048576 == 0) {
  141.             std::cout << (bytes >> 20) << "MB lag=" << lag << "(" << maxlag << ")\n"
  142.                 << std::flush;
  143.         }
  144.     }
  145.     char buffer3[4] = {0};
  146.     for(uint64_t i = 0; i < lag; i++)
  147.         out.write(buffer3, 4);
  148.     std::cout << (bytes >> 20) << "MB lag=" << lag << "(" << maxlag << ")\n" << std::flush;
  149.     std::cout << std::endl <<  "Found " << gaps << " gaps." << std::endl;
  150.     return 0;
  151. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement