Advertisement
Guest User

Untitled

a guest
Aug 15th, 2017
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.04 KB | None | 0 0
  1. static auto avFormatDeleter = [](AVFormatContext* fmtCtx){ avformat_close_input(&fmtCtx); };
  2.  
  3. AudioFile::AudioFile(const std::string &fileName, unsigned int sampleRate) :
  4. AudioLoop(sampleRate), filepath_(fileName), updatePlaybackScale_(0)
  5. {
  6. int ret = 0;
  7. std::unique_ptr<AVFormatContext, std::function<void(AVFormatContext*)>> fmtCtx =
  8. std::unique_ptr<AVFormatContext, std::function<void(AVFormatContext*)>>(nullptr, avFormatDeleter);
  9.  
  10. AVFormatContext* ctx = avformat_alloc_context();
  11. if ((ret = avformat_open_input(&ctx, fileName.c_str(), 0, 0)) < 0)
  12. throw AudioFileException("Could not open " + fileName);
  13.  
  14. // take ownership so avformat_close_input is always called
  15. fmtCtx.reset(ctx);
  16.  
  17. if ((ret = avformat_find_stream_info(fmtCtx.get(), 0)) < 0)
  18. throw AudioFileException("Failed to find stream info in " + fileName);
  19.  
  20. if ((ret = av_find_best_stream(fmtCtx.get(), AVMEDIA_TYPE_AUDIO, -1, -1, 0, 0)) < 0)
  21. throw AudioFileException("No audio stream in " + fileName);
  22.  
  23. AVStream* stream = fmtCtx->streams[ret];
  24. int nbSamples = 0;
  25. int nbChannels = stream->codecpar->channels;
  26. int sRate = stream->codecpar->sample_rate;
  27.  
  28. AVCodec* codec = avcodec_find_decoder(stream->codecpar->codec_id);
  29. if (!codec)
  30. throw AudioFileException("No decoder found for " + fileName);
  31.  
  32. AVCodecContext* codecCtx = avcodec_alloc_context3(codec);
  33. avcodec_parameters_to_context(codecCtx, stream->codecpar);
  34. switch (nbChannels) {
  35. case 1:
  36. codecCtx->channel_layout = AV_CH_LAYOUT_MONO;
  37. break;
  38. case 2:
  39. codecCtx->channel_layout = AV_CH_LAYOUT_STEREO;
  40. break;
  41. default:
  42. throw AudioFileException("Unsupported number of channels");
  43. }
  44. if ((ret = avcodec_open2(codecCtx, codec, 0)) < 0)
  45. throw AudioFileException("Could not open codec " + std::string(avcodec_get_name(codecCtx->codec_id)));
  46.  
  47. const int outRate = static_cast<int32_t>(sRate);
  48. const bool isPlanar = av_sample_fmt_is_planar(codecCtx->sample_fmt);
  49. const bool needsResampling = (av_get_bytes_per_sample(codecCtx->sample_fmt) != 2) || (sRate == outRate);
  50.  
  51. SwrContext* swrCtx = swr_alloc();
  52. switch (nbChannels) {
  53. case 1:
  54. av_opt_set_channel_layout(swrCtx, "in_channel_layout", AV_CH_LAYOUT_MONO, 0);
  55. break;
  56. case 2:
  57. av_opt_set_channel_layout(swrCtx, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0);
  58. break;
  59. default:
  60. throw AudioFileException("Unsupported number of channels");
  61. }
  62. av_opt_set_channel_layout(swrCtx, "out_channel_layout", AV_CH_LAYOUT_MONO, 0);
  63. av_opt_set_int(swrCtx, "in_sample_rate", sRate, 0);
  64. av_opt_set_int(swrCtx, "out_sample_rate", outRate, 0);
  65. av_opt_set_sample_fmt(swrCtx, "in_sample_fmt", codecCtx->sample_fmt, 0);
  66. av_opt_set_sample_fmt(swrCtx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); // match AudioSample
  67. if ((ret = swr_init(swrCtx)) < 0)
  68. throw AudioFileException("Failed to initialize resampling context");
  69.  
  70. AVFrame* frame = av_frame_alloc();
  71. AVPacket pkt;
  72. av_init_packet(&pkt);
  73. std::vector<int16_t> buf;
  74. while ((ret = av_read_frame(fmtCtx.get(), &pkt)) >= 0) {
  75. ret = avcodec_send_packet(codecCtx, &pkt);
  76. //if (ret == AVERROR_EOF) continue;
  77. if (ret < 0) break;
  78.  
  79. while (ret >= 0) {
  80. ret = avcodec_receive_frame(codecCtx, frame);
  81. if (ret == AVERROR(EAGAIN) && ret != AVERROR_EOF)
  82. break;
  83. else if (ret >= 0) {
  84. AVFrame* output = av_frame_alloc();
  85. if (needsResampling) {
  86. output->format = AV_SAMPLE_FMT_S16; // match AudioSample
  87. output->sample_rate = outRate;
  88. output->channel_layout = AV_CH_LAYOUT_MONO;
  89. if ((ret = swr_config_frame(swrCtx, output, frame)) < 0) {
  90. char errbuf[1024];
  91. av_strerror(ret, errbuf, sizeof(errbuf));
  92. RING_WARN("swr_config_frame returned %d (%s)", ret, errbuf);
  93. }
  94. if ((ret = swr_convert_frame(swrCtx, output, frame)) < 0) {
  95. char errbuf[1024];
  96. av_strerror(ret, errbuf, sizeof(errbuf));
  97. RING_WARN("swr_convert_frame returned %d (%s)", ret, errbuf);
  98. }
  99. } else {
  100. av_frame_copy(output, frame);
  101. av_frame_copy_props(output, frame);
  102. }
  103.  
  104. nbSamples += output->nb_samples;
  105. int sz = output->nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);
  106. for (int i = 0; i < sz; ++i) {
  107. buf.push_back(output->extended_data[0][i]);
  108. }
  109.  
  110. av_packet_unref(&pkt);
  111. av_frame_free(&output);
  112. }
  113. }
  114. if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) break;
  115. }
  116.  
  117. av_frame_free(&frame);
  118.  
  119. if (ret < 0 && ret != AVERROR_EOF)
  120. throw AudioFileException("Error while decoding " + fileName);
  121.  
  122. AudioSample* samples = buf.data();
  123. AudioBuffer* b = new AudioBuffer(samples, nbSamples, AudioFormat(outRate, 1));
  124. delete buffer_;
  125. buffer_ = b;
  126.  
  127. // int format;
  128. // bool hasHeader = true;
  129. //
  130. // if (filepath_.find(".wav") != std::string::npos) {
  131. // format = SF_FORMAT_WAV;
  132. // } else if (filepath_.find(".ul") != std::string::npos) {
  133. // format = SF_FORMAT_RAW | SF_FORMAT_ULAW;
  134. // hasHeader = false;
  135. // } else if (filepath_.find(".al") != std::string::npos) {
  136. // format = SF_FORMAT_RAW | SF_FORMAT_ALAW;
  137. // hasHeader = false;
  138. // } else if (filepath_.find(".au") != std::string::npos) {
  139. // format = SF_FORMAT_AU;
  140. // } else if (filepath_.find(".flac") != std::string::npos) {
  141. // format = SF_FORMAT_FLAC;
  142. // } else if (filepath_.find(".ogg") != std::string::npos) {
  143. // format = SF_FORMAT_OGG;
  144. // } else {
  145. // RING_WARN("No file extension, guessing WAV");
  146. // format = SF_FORMAT_WAV;
  147. // }
  148. //
  149. // SndfileHandle fileHandle(fileName.c_str(), SFM_READ, format, hasHeader ? 0 : 1,
  150. // hasHeader ? 0 : 8000);
  151. //
  152. // if (!fileHandle)
  153. // throw AudioFileException("File handle " + fileName + " could not be created");
  154. // if (fileHandle.error()) {
  155. // RING_ERR("Error fileHandle: %s", fileHandle.strError());
  156. // throw AudioFileException("File " + fileName + " doesn't exist");
  157. // }
  158. //
  159. // switch (fileHandle.channels()) {
  160. // case 1:
  161. // case 2:
  162. // break;
  163. // default:
  164. // throw AudioFileException("Unsupported number of channels");
  165. // }
  166. //
  167. // // get # of bytes in file
  168. // const size_t fileSize = fileHandle.seek(0, SEEK_END);
  169. // fileHandle.seek(0, SEEK_SET);
  170. //
  171. // const sf_count_t nbFrames = hasHeader ? fileHandle.frames() : fileSize / fileHandle.channels();
  172. //
  173. // AudioSample * interleaved = new AudioSample[nbFrames * fileHandle.channels()];
  174. //
  175. // // get n "items", aka samples (not frames)
  176. // fileHandle.read(interleaved, nbFrames * fileHandle.channels());
  177. //
  178. // AudioBuffer * buffer = new AudioBuffer(nbFrames, AudioFormat(fileHandle.samplerate(), fileHandle.channels()));
  179. // buffer->deinterleave(interleaved, nbFrames, fileHandle.channels());
  180. // delete [] interleaved;
  181. //
  182. // const int rate = static_cast<int32_t>(sampleRate);
  183. //
  184. // if (fileHandle.samplerate() != rate) {
  185. // Resampler resampler(std::max(fileHandle.samplerate(), rate), fileHandle.channels(), true);
  186. // AudioBuffer * resampled = new AudioBuffer(nbFrames, AudioFormat(rate, fileHandle.channels()));
  187. // resampler.resample(*buffer, *resampled);
  188. // delete buffer;
  189. // delete buffer_;
  190. // buffer_ = resampled;
  191. // } else {
  192. // delete buffer_;
  193. // buffer_ = buffer;
  194. // }
  195. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement