+ _info.channels = other.n_channels();
+ _info.samplerate = other.sample_rate ();
+ _info.format = SF_FORMAT_FLAC | (use16bits ? SF_FORMAT_PCM_16 : SF_FORMAT_PCM_24);
+
+ /* flac is either read or write -- never both,
+ * so we need to special-case ::open () */
+#ifdef PLATFORM_WINDOWS
+ int fd = g_open (_path.c_str(), O_CREAT | O_RDWR, 0644);
+#else
+ int fd = ::open (_path.c_str(), O_CREAT | O_RDWR, 0644);
+#endif
+ if (fd == -1) {
+ throw failed_constructor();
+ }
+
+ _sndfile = sf_open_fd (fd, SFM_WRITE, &_info, true);
+
+ if (_sndfile == 0) {
+ throw failed_constructor();
+ }
+
+ Sample buf[8192];
+ framecnt_t off = 0;
+ float peak = 0;
+ float norm = 1.f;
+
+ /* normalize before converting to fixed point, calc gain factor */
+ framecnt_t len = other.read (buf, off, 8192, /*channel*/0);
+ while (len > 0) {
+ peak = compute_peak (buf, len, peak);
+ off += len;
+ len = other.read (buf, off, 8192, /*channel*/0);
+ if (progress) {
+ progress->set_progress (0.5f * (float) off / other.readable_length ());
+ }
+ }
+
+ if (peak > 0) {
+ _gain *= peak;
+ norm = 1.f / peak;
+ }
+
+ /* copy file */
+ off = 0;
+ len = other.read (buf, off, 8192, /*channel*/0);
+ while (len > 0) {
+ if (norm != 1.f) {
+ for (framecnt_t i = 0; i < len; ++i) {
+ buf[i] *= norm;
+ }
+ }
+ write (buf, len);
+ off += len;
+ len = other.read (buf, off, 8192, /*channel*/0);
+ if (progress) {
+ progress->set_progress (0.5f + 0.5f * (float) off / other.readable_length ());
+ }
+ }
+}
+
+void
+SndFileSource::init_sndfile ()
+{