Advertisement
DavidNorgren

Untitled

Jan 24th, 2016
198
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.81 KB | None | 0 0
  1. #pragma comment (lib, "libavutil.a")
  2. #pragma comment (lib, "libavformat.a")
  3. #pragma comment (lib, "libavcodec.a")
  4. #pragma comment (lib, "libswresample.a")
  5. #pragma comment (lib, "libswscale.a")
  6.  
  7. #include <Windows.h>
  8. #include <string.h>
  9. #include <math.h>
  10. #include <vector>
  11. #include <iostream>
  12.  
  13. extern "C" {
  14.     #include <libavutil/opt.h>
  15.     #include <libavutil/mathematics.h>
  16.     #include <libavformat/avformat.h>
  17.     #include <libswscale/swscale.h>
  18.     #include <libswresample/swresample.h>
  19. }
  20.  
  21. #define RAW_AUDIO_FRAME_SIZE            1152
  22. #define STREAM_AUDIO_BIT_RATE           320000
  23. #define STREAM_AUDIO_SAMPLE_RATE        44100
  24. #define STREAM_AUDIO_SAMPLE_FORMAT_GM   AV_SAMPLE_FMT_S16P
  25. #define STREAM_AUDIO_SAMPLE_FORMAT_MP3  AV_SAMPLE_FMT_S16P
  26. #define STREAM_AUDIO_SAMPLE_TYPE        int16_t
  27. #define STREAM_AUDIO_SAMPLE_MAX         SHRT_MAX
  28. #define STREAM_AUDIO_SAMPLE_MIN         SHRT_MIN
  29. #define STREAM_AUDIO_CHANNEL_LAYOUT     AV_CH_LAYOUT_STEREO
  30. #define STREAM_AUDIO_CHANNELS           2
  31.  
  32. using namespace std;
  33.  
  34. // A file of raw data
  35. typedef struct File {
  36.     vector<AVFrame*> frames;
  37. } File;
  38.  
  39. // A sound
  40. typedef struct Sound {
  41.     //vector<AVFrame*> frames;
  42.     uint64_t play;
  43.     double volume;
  44.     File* file;
  45. } Sound;
  46.  
  47. // Media file output
  48. AVFormatContext *outContext;
  49. uint64_t totalFrames;
  50.  
  51. // Audio
  52. AVStream *audioStream;
  53. AVCodec *audioCodec;
  54. AVCodecContext *audioCodecContext;
  55. AVRational audioTimeBase;
  56. uint64_t audioFrameNum;
  57.  
  58. // Files
  59. vector<File*> files;
  60. vector<Sound*> sounds;
  61.  
  62.  
  63. // Converts to a wide string
  64. wstring towstr(const string str) {
  65.     wstring buffer;
  66.     buffer.resize(MultiByteToWideChar(CP_UTF8, 0, &str[0], -1, 0, 0));
  67.     MultiByteToWideChar(CP_UTF8, 0, &str[0], -1, &buffer[0], buffer.size());
  68.     return &buffer[0];
  69. }
  70.  
  71.  
  72. // Create an AVRational
  73. AVRational rat(int num, int den) {
  74.     AVRational r;
  75.     r.num = num;
  76.     r.den = den;
  77.     return r;
  78. }
  79.  
  80.  
  81. // Initialize codecs
  82. double audio_init() {
  83.  
  84.     // Initialize libavcodec, and register all codecs and formats.
  85.     av_register_all();
  86.     return 0;
  87.  
  88. }
  89.  
  90.  
  91. // Decode a file into raw audio
  92. double audio_file_decode(const char *source, const char *dest, float pitch) {
  93.  
  94.     FILE* outStream = NULL;
  95.     AVFormatContext *formatContext = NULL;
  96.     AVCodec *codec = NULL;
  97.     AVCodecContext *codecContext = NULL;
  98.     SwrContext *swrContext = NULL;
  99.     AVFrame *frameDecoded = NULL;
  100.     AVPacket inPacket;
  101.     int ret = 0;
  102.     av_init_packet(&inPacket);
  103.  
  104.     try {
  105.  
  106.         // Create writer
  107.         _wfopen_s(&outStream, &towstr(dest)[0], L"wb");
  108.  
  109.         // Create contex
  110.         formatContext = avformat_alloc_context();
  111.         if (avformat_open_input(&formatContext, source, NULL, NULL) < 0)
  112.             throw -11;
  113.  
  114.         // Find info
  115.         if (avformat_find_stream_info(formatContext, 0) < 0)
  116.             throw -12;
  117.  
  118.         // Find audio stream
  119.         int streamId = av_find_best_stream(formatContext, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
  120.         if (streamId < 0)
  121.             throw -13;
  122.  
  123.         codecContext = avcodec_alloc_context3(codec);
  124.         avcodec_copy_context(codecContext, formatContext->streams[streamId]->codec);
  125.  
  126.         // Open codec
  127.         if (avcodec_open2(codecContext, codec, 0) < 0)
  128.             throw -14;
  129.  
  130.         // Set up resample context
  131.         swrContext = swr_alloc();
  132.         if (!swrContext)
  133.             throw -15;
  134.  
  135.         av_opt_set_int(swrContext, "in_channel_count", codecContext->channels, 0);
  136.         av_opt_set_int(swrContext, "in_channel_layout", codecContext->channel_layout, 0);
  137.         av_opt_set_int(swrContext, "in_sample_rate", codecContext->sample_rate, 0);
  138.         av_opt_set_sample_fmt(swrContext, "in_sample_fmt", codecContext->sample_fmt, 0);
  139.  
  140.         av_opt_set_int(swrContext, "out_channel_count", STREAM_AUDIO_CHANNELS, 0);
  141.         av_opt_set_int(swrContext, "out_channel_layout", STREAM_AUDIO_CHANNEL_LAYOUT, 0);
  142.         av_opt_set_int(swrContext, "out_sample_rate", STREAM_AUDIO_SAMPLE_RATE / pitch, 0);
  143.         av_opt_set_sample_fmt(swrContext, "out_sample_fmt", STREAM_AUDIO_SAMPLE_FORMAT_GM, 0);
  144.  
  145.         if (swr_init(swrContext))
  146.             throw -16;
  147.  
  148.         // Allocate re-usable frame
  149.         frameDecoded = av_frame_alloc();
  150.         if (!frameDecoded)
  151.             throw -17;
  152.  
  153.         frameDecoded->format = codecContext->sample_fmt;
  154.         frameDecoded->channel_layout = codecContext->channel_layout;
  155.         frameDecoded->channels = codecContext->channels;
  156.         frameDecoded->sample_rate = codecContext->sample_rate;
  157.  
  158.         // Load frames
  159.         inPacket.data = NULL;
  160.         inPacket.size = 0;
  161.  
  162.         int gotFrame, samples = 0;
  163.  
  164.         while (av_read_frame(formatContext, &inPacket) >= 0) {
  165.          
  166.             if (inPacket.stream_index != streamId)
  167.                 continue;
  168.          
  169.             if (avcodec_decode_audio4(codecContext, frameDecoded, &gotFrame, &inPacket) < 0)
  170.                 throw -18;
  171.          
  172.             if (!gotFrame)
  173.                 continue;
  174.          
  175.             // Begin conversion
  176.             //if (swr_convert(swrContext, NULL, 0, (const uint8_t **)frameDecoded->data, frameDecoded->nb_samples) < 0)
  177.             //  throw -19;
  178.          
  179.             //while (swr_get_out_samples(swrContext, 0) >= RAW_AUDIO_FRAME_SIZE) {
  180.                        
  181.                 // Allocate data
  182.                 uint8_t **convertedData = NULL;
  183.                 if (av_samples_alloc_array_and_samples(&convertedData, NULL, STREAM_AUDIO_CHANNELS, RAW_AUDIO_FRAME_SIZE, STREAM_AUDIO_SAMPLE_FORMAT_GM, 0) < 0)
  184.                     throw -20;
  185.          
  186.                 // Convert
  187.                 int outSamples = swr_convert(swrContext, convertedData, RAW_AUDIO_FRAME_SIZE, (const uint8_t **)frameDecoded->data, frameDecoded->nb_samples);
  188.                 if (outSamples < 0)
  189.                     throw -21;
  190.          
  191.                 // Calculate buffer size
  192.                 //size_t bufferSize = av_samples_get_buffer_size(NULL, STREAM_AUDIO_CHANNELS, RAW_AUDIO_FRAME_SIZE, STREAM_AUDIO_SAMPLE_FORMAT_GM, 0);
  193.                 //if (bufferSize < 0)
  194.                 //  throw -22;
  195.          
  196.                 fwrite(convertedData[0], 1, outSamples * sizeof(STREAM_AUDIO_SAMPLE_TYPE) * STREAM_AUDIO_CHANNELS, outStream);
  197.                 av_freep(convertedData);
  198.             //}
  199.         }
  200.          
  201.         // Flush
  202.         cout << "flushing.." << endl;
  203.         while (1) {
  204.            
  205.             // Allocate data
  206.             uint8_t **convertedData = NULL;
  207.             if (av_samples_alloc_array_and_samples(&convertedData, NULL, STREAM_AUDIO_CHANNELS, RAW_AUDIO_FRAME_SIZE, STREAM_AUDIO_SAMPLE_FORMAT_GM, 0) < 0)
  208.                 throw -20;
  209.          
  210.             // Convert
  211.             int outSamples = swr_convert(swrContext, convertedData, RAW_AUDIO_FRAME_SIZE, NULL, 0);
  212.             if (outSamples < 0)
  213.                 throw -21;
  214.          
  215.             cout << "Flushed " << outSamples << endl;
  216.             //cout << ret << endl;
  217.             if (outSamples==0)
  218.                 break;
  219.          
  220.             // Calculate buffer size
  221.             //size_t bufferSize = av_samples_get_buffer_size(NULL, STREAM_AUDIO_CHANNELS, RAW_AUDIO_FRAME_SIZE, STREAM_AUDIO_SAMPLE_FORMAT_GM, 0);
  222.             //if (bufferSize < 0)
  223.             //  throw -22;
  224.          
  225.             fwrite(convertedData[0], 1, outSamples * sizeof(STREAM_AUDIO_SAMPLE_TYPE) * STREAM_AUDIO_CHANNELS, outStream);
  226.             av_freep(convertedData);
  227.         }
  228.     }
  229.     catch (int e) {
  230.         ret = e;
  231.     }
  232.  
  233.     // Clean up
  234.     if (frameDecoded)
  235.         av_frame_free(&frameDecoded);
  236.     if (swrContext)
  237.         swr_free(&swrContext);
  238.     if (codecContext)
  239.         avcodec_close(codecContext);
  240.     if (formatContext) {
  241.         avformat_close_input(&formatContext);
  242.         avformat_free_context(formatContext);
  243.     }
  244.     av_free_packet(&inPacket);
  245.  
  246.  
  247.     // Close
  248.     if (outStream)
  249.         fclose(outStream);
  250.  
  251.     return ret;
  252.  
  253. }
  254.  
  255.  
  256. // Save audio file
  257. double audio_start(const char* outFile) {
  258.  
  259.     // Allocate the output media context
  260.     avformat_alloc_output_context2(&outContext, NULL, NULL, outFile);
  261.     if (!outContext)
  262.         return -1;
  263.    
  264.     // Find audio encoder
  265.     audioCodec = avcodec_find_encoder(outContext->oformat->audio_codec); // CODEC_ID_MP3
  266.     if (!audioCodec)
  267.         return -2;
  268.  
  269.     // Start audio stream
  270.     audioStream = avformat_new_stream(outContext, audioCodec);
  271.     if (!audioStream)
  272.         return -3;
  273.  
  274.     audioCodecContext = audioStream->codec;
  275.     audioStream->id = 0;
  276.  
  277.     // Setup
  278.     audioCodecContext->sample_fmt = STREAM_AUDIO_SAMPLE_FORMAT_MP3;
  279.     audioCodecContext->sample_rate = STREAM_AUDIO_SAMPLE_RATE;
  280.     audioCodecContext->bit_rate = STREAM_AUDIO_BIT_RATE;
  281.     audioCodecContext->channels = STREAM_AUDIO_CHANNELS;
  282.     audioCodecContext->channel_layout = STREAM_AUDIO_CHANNEL_LAYOUT;
  283.  
  284.     if (outContext->oformat->flags & AVFMT_GLOBALHEADER)
  285.         audioCodecContext->flags |= CODEC_FLAG_GLOBAL_HEADER;
  286.  
  287.     // Open the codec
  288.     if (avcodec_open2(audioCodecContext, audioCodec, NULL) < 0)
  289.         return -4;
  290.  
  291.     // Open the output file
  292.     if (avio_open(&outContext->pb, outFile, AVIO_FLAG_WRITE) < 0)
  293.         return -5;
  294.  
  295.     audioFrameNum = 0;
  296.     audioTimeBase = rat(audioCodecContext->frame_size, STREAM_AUDIO_SAMPLE_RATE);
  297.     cout << "frame_size = " << audioCodecContext->frame_size << endl;
  298.  
  299.     // Write the stream header, if any.
  300.     if (avformat_write_header(outContext, NULL) < 0)
  301.         return -10;
  302.  
  303.     totalFrames = 0;
  304.  
  305.     return 0;
  306.  
  307. }
  308.  
  309.  
  310. // Adds a file with raw audio, returns the id
  311. double audio_file_add(const char* source) {
  312.  
  313.     // Create file
  314.     File* file = new File();
  315.     files.push_back(file);
  316.  
  317.     // Create reader
  318.     FILE* inStream;
  319.     _wfopen_s(&inStream, &towstr(source)[0], L"rb");
  320.  
  321.     // Read to EOF, store data in frames
  322.     size_t bufferSize = av_samples_get_buffer_size(NULL, STREAM_AUDIO_CHANNELS, audioCodecContext->frame_size, STREAM_AUDIO_SAMPLE_FORMAT_GM, 0);
  323.    
  324.     while (1) {
  325.         uint8_t* rawData = new uint8_t[bufferSize];
  326.         int len = fread(rawData, 1, bufferSize, inStream);
  327.  
  328.         if (!len)
  329.             break;
  330.  
  331.         // Allocate frame
  332.         AVFrame *frame = av_frame_alloc();
  333.         if (!frame)
  334.             return -23;
  335.  
  336.         frame->nb_samples = audioCodecContext->frame_size;
  337.         frame->format = STREAM_AUDIO_SAMPLE_FORMAT_GM;
  338.         frame->channel_layout = STREAM_AUDIO_CHANNEL_LAYOUT;
  339.         frame->channels = STREAM_AUDIO_CHANNELS;
  340.         frame->sample_rate = STREAM_AUDIO_SAMPLE_RATE;
  341.  
  342.         // Fill frame
  343.         if (avcodec_fill_audio_frame(frame, STREAM_AUDIO_CHANNELS, STREAM_AUDIO_SAMPLE_FORMAT_GM, rawData, len, 0) < 0)
  344.             return -24;
  345.  
  346.         file->frames.push_back(frame);
  347.     }
  348.  
  349.     // Close
  350.     fclose(inStream);
  351.  
  352.     // Return ID
  353.     return files.size() - 1;
  354.  
  355. }
  356.  
  357.  
  358. // Adds a sound to the export
  359. double audio_sound_add(double fileId, double play, double pitch, double volume) {
  360.  
  361.     Sound* sound = new Sound();
  362.     sound->file = files[(int)fileId];
  363.     sound->play = av_rescale_q(play * 1000, rat(1, 1000), audioTimeBase);
  364.     sound->volume = volume;
  365.     sounds.push_back(sound);
  366.    
  367.     totalFrames = max(totalFrames, sound->play + sound->file->frames.size());
  368.     cout << "Added sound at time " << play << ", frame " << sound->play << ", volume " << volume << ", pitch " << pitch << endl;
  369.    
  370.     return 0;
  371.  
  372. }
  373.  
  374.  
  375. // Combine files together
  376. double audio_combine() {
  377.    
  378.     uint64_t audioFrameNum = 0;
  379.     int dataSize = sizeof(STREAM_AUDIO_SAMPLE_TYPE);
  380.     int isPlanar = av_sample_fmt_is_planar(STREAM_AUDIO_SAMPLE_FORMAT_MP3);
  381.  
  382.     while (audioFrameNum < totalFrames) {
  383.  
  384.         // Allocate frame
  385.         AVFrame *frame = av_frame_alloc();
  386.         if (!frame)
  387.             return -1;
  388.  
  389.         frame->nb_samples = audioCodecContext->frame_size;
  390.         frame->format = STREAM_AUDIO_SAMPLE_FORMAT_MP3;
  391.         frame->channel_layout = STREAM_AUDIO_CHANNEL_LAYOUT;
  392.         frame->channels = STREAM_AUDIO_CHANNELS;
  393.         frame->sample_rate = STREAM_AUDIO_SAMPLE_RATE;
  394.  
  395.         if (av_frame_get_buffer(frame, 0) < 0)
  396.             return -2;
  397.  
  398.         if (av_frame_make_writable(frame) < 0)
  399.             return -3;
  400.  
  401.         // Find sounds
  402.         vector<Sound*> frameSounds;
  403.         for (unsigned int i = 0; i < sounds.size(); i++)
  404.             if (audioFrameNum >= sounds[i]->play &&  audioFrameNum < sounds[i]->play + sounds[i]->file->frames.size())
  405.                 frameSounds.push_back(sounds[i]);
  406.  
  407.         // Write to frame (mix sounds)
  408.  
  409.         for (int c = 0; c < 1 + isPlanar; c++) {
  410.             for (int i = 0; i < frame->linesize[0]; i += dataSize) {
  411.                 STREAM_AUDIO_SAMPLE_TYPE dstVal = 0; // 0=silence
  412.  
  413.                 for (unsigned int j = 0; j < frameSounds.size(); j++) {
  414.                     STREAM_AUDIO_SAMPLE_TYPE srcVal;
  415.                     memcpy(&srcVal, &frameSounds[j]->file->frames[audioFrameNum - frameSounds[j]->play]->data[c][i], dataSize);
  416.  
  417.                     // Clamp audio
  418.                     double tmp = (double)dstVal + (double)(srcVal * frameSounds[j]->volume);
  419.                     if (tmp > STREAM_AUDIO_SAMPLE_MAX)
  420.                         tmp = STREAM_AUDIO_SAMPLE_MAX;
  421.                     if (tmp < STREAM_AUDIO_SAMPLE_MIN)
  422.                         tmp = STREAM_AUDIO_SAMPLE_MIN;
  423.                     dstVal = tmp;
  424.                 }
  425.  
  426.                 memcpy(&frame->data[c][i], &dstVal, dataSize);
  427.             }
  428.         }
  429.  
  430.         frame->pts = av_rescale_q(audioFrameNum, audioTimeBase, audioCodecContext->time_base);
  431.  
  432.         // Allocate packet
  433.         int gotPacket;
  434.         AVPacket outPacket;
  435.         av_init_packet(&outPacket);
  436.         outPacket.data = NULL;
  437.         outPacket.size = 0;
  438.  
  439.         // Encode
  440.         if (avcodec_encode_audio2(audioCodecContext, &outPacket, frame, &gotPacket) < 0)
  441.             return -4;
  442.  
  443.         // Write to file
  444.         if (gotPacket) {
  445.             av_packet_rescale_ts(&outPacket, audioCodecContext->time_base, audioStream->time_base);
  446.             outPacket.stream_index = audioStream->index;
  447.  
  448.             if (av_interleaved_write_frame(outContext, &outPacket) != 0)
  449.                 return -5;
  450.         }
  451.  
  452.         // Free
  453.         av_frame_free(&frame);
  454.         av_free_packet(&outPacket);
  455.  
  456.         // Advance
  457.         audioFrameNum++;
  458.  
  459.     }
  460.  
  461.     // Flush audio
  462.     while (1) {
  463.         int gotPacket;
  464.         AVPacket flushPacket;
  465.         av_init_packet(&flushPacket);
  466.         flushPacket.data = NULL;
  467.         flushPacket.size = 0;
  468.  
  469.         if (avcodec_encode_audio2(audioCodecContext, &flushPacket, NULL, &gotPacket) < 0)
  470.             return -36;
  471.  
  472.         if (gotPacket) {
  473.             flushPacket.stream_index = audioStream->index;
  474.  
  475.             if (av_interleaved_write_frame(outContext, &flushPacket) != 0)
  476.                 return -37;
  477.         }
  478.  
  479.         av_free_packet(&flushPacket);
  480.  
  481.         if (!gotPacket)
  482.             break;
  483.     }
  484.  
  485.     // Clear files
  486.     for (size_t i = 0; i < files.size(); i++) {
  487.         for (size_t j = 0; j < files[i]->frames.size(); j++)
  488.             avcodec_free_frame(&files[i]->frames[j]);
  489.         delete files[i];
  490.     }
  491.     files.clear();
  492.  
  493.     // Clear sounds
  494.     for (size_t i = 0; i < sounds.size(); i++) {
  495.         delete sounds[i];
  496.     }
  497.     sounds.clear();
  498.  
  499.     // Write the trailer
  500.     av_write_trailer(outContext);
  501.    
  502.     // Close audio
  503.     avcodec_close(audioCodecContext);
  504.  
  505.     // Close the output file.
  506.     avio_close(outContext->pb);
  507.  
  508.     // Free the stream
  509.     avformat_free_context(outContext);
  510.  
  511.     return 0;
  512. }
  513.  
  514. int main() {
  515.     audio_init();
  516.     audio_start("out.mp3");
  517.     for (int i=0; i<25; i++) {
  518.         audio_file_decode("note.ogg", "snd.au", 1-i*0.025);
  519.         double note = audio_file_add("snd.au");
  520.         audio_sound_add(note, i*0.5, 1-i*0.025, 1);
  521.     }
  522.     cout << "Writing to file..." << endl;
  523.     audio_combine();
  524.     cout << "done!" << endl;
  525.     int x;
  526.     cin >> x;
  527. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement