Example #1
0
int ExportFLAC::Export(AudacityProject *project,
                        int numChannels,
                        const wxString &fName,
                        bool selectionOnly,
                        double t0,
                        double t1,
                        MixerSpec *mixerSpec,
                        const Tags *metadata,
                        int WXUNUSED(subformat))
{
   double    rate    = project->GetRate();
   TrackList *tracks = project->GetTracks();

   wxLogNull logNo;            // temporarily disable wxWidgets error messages
   int updateResult = eProgressSuccess;

   int levelPref;
   gPrefs->Read(wxT("/FileFormats/FLACLevel"), &levelPref, 5);

   wxString bitDepthPref =
      gPrefs->Read(wxT("/FileFormats/FLACBitDepth"), wxT("16"));

   FLAC::Encoder::File encoder;

#ifdef LEGACY_FLAC
   encoder.set_filename(OSOUTPUT(fName));
#endif
   encoder.set_channels(numChannels);
   encoder.set_sample_rate(lrint(rate));

   // See note in GetMetadata() about a bug in libflac++ 1.1.2
   if (!GetMetadata(project, metadata)) {
      return false;
   }

   if (mMetadata) {
      encoder.set_metadata(&mMetadata, 1);
   }

   sampleFormat format;
   if (bitDepthPref == wxT("24")) {
      format = int24Sample;
      encoder.set_bits_per_sample(24);
   } else { //convert float to 16 bits
      format = int16Sample;
      encoder.set_bits_per_sample(16);
   }

   // Duplicate the flac command line compression levels
   if (levelPref < 0 || levelPref > 8) {
      levelPref = 5;
   }
   encoder.set_do_exhaustive_model_search(flacLevels[levelPref].do_exhaustive_model_search);
   encoder.set_do_escape_coding(flacLevels[levelPref].do_escape_coding);
   if (numChannels != 2) {
      encoder.set_do_mid_side_stereo(false);
      encoder.set_loose_mid_side_stereo(false);
   }
   else {
      encoder.set_do_mid_side_stereo(flacLevels[levelPref].do_mid_side_stereo);
      encoder.set_loose_mid_side_stereo(flacLevels[levelPref].loose_mid_side_stereo);
   }
   encoder.set_qlp_coeff_precision(flacLevels[levelPref].qlp_coeff_precision);
   encoder.set_min_residual_partition_order(flacLevels[levelPref].min_residual_partition_order);
   encoder.set_max_residual_partition_order(flacLevels[levelPref].max_residual_partition_order);
   encoder.set_rice_parameter_search_dist(flacLevels[levelPref].rice_parameter_search_dist);
   encoder.set_max_lpc_order(flacLevels[levelPref].max_lpc_order);

#ifdef LEGACY_FLAC
   encoder.init();
#else
   wxFFile f;     // will be closed when it goes out of scope
   if (!f.Open(fName, wxT("w+b"))) {
      wxMessageBox(wxString::Format(_("FLAC export couldn't open %s"), fName.c_str()));
      return false;
   }

   // Even though there is an init() method that takes a filename, use the one that
   // takes a file handle because wxWidgets can open a file with a Unicode name and
   // libflac can't (under Windows).
   int status = encoder.init(f.fp());
   if (status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
      wxMessageBox(wxString::Format(_("FLAC encoder failed to initialize\nStatus: %d"), status));
      return false;
   }
#endif

   if (mMetadata) {
      ::FLAC__metadata_object_delete(mMetadata);
   }

   int numWaveTracks;
   WaveTrack **waveTracks;
   tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
   Mixer *mixer = CreateMixer(numWaveTracks, waveTracks,
                            tracks->GetTimeTrack(),
                            t0, t1,
                            numChannels, SAMPLES_PER_RUN, false,
                            rate, format, true, mixerSpec);
   delete [] waveTracks;

   int i, j;
   FLAC__int32 **tmpsmplbuf = new FLAC__int32*[numChannels];
   for (i = 0; i < numChannels; i++) {
      tmpsmplbuf[i] = (FLAC__int32 *) calloc(SAMPLES_PER_RUN, sizeof(FLAC__int32));
   }

   {
      ProgressDialog progress(wxFileName(fName).GetName(),
         selectionOnly ?
         _("Exporting the selected audio as FLAC") :
         _("Exporting the entire project as FLAC"));

      while (updateResult == eProgressSuccess) {
         sampleCount samplesThisRun = mixer->Process(SAMPLES_PER_RUN);
         if (samplesThisRun == 0) { //stop encoding
            break;
         }
         else {
            for (i = 0; i < numChannels; i++) {
               samplePtr mixed = mixer->GetBuffer(i);
               if (format == int24Sample) {
                  for (j = 0; j < samplesThisRun; j++) {
                     tmpsmplbuf[i][j] = ((int *)mixed)[j];
                  }
               }
               else {
                  for (j = 0; j < samplesThisRun; j++) {
                     tmpsmplbuf[i][j] = ((short *)mixed)[j];
                  }
               }
            }
            encoder.process(tmpsmplbuf, samplesThisRun);
         }
         updateResult = progress.Update(mixer->MixGetCurrentTime() - t0, t1 - t0);
      }
      f.Detach(); // libflac closes the file
      encoder.finish();
   }

   for (i = 0; i < numChannels; i++) {
      free(tmpsmplbuf[i]);
   }
   delete mixer;

   delete[] tmpsmplbuf;

   return updateResult;
}
Example #2
0
/**
 *	dop_track_helper
 */
int dop_track_helper(
	boost::filesystem::path outpath,
	DsdSampleReader* dsr,
	dsf2flac_int64 startPos,
	dsf2flac_int64 endPos,
	ID3_Tag	id3tag)
{

	// double check the start and end positions!
	if ( startPos > dsr->getLength()-1 )
		startPos = dsr->getLength()-1;
	if ( endPos > dsr->getLength() )
		endPos = dsr->getLength();

	// create a dop packer object.
	DopPacker dopp = DopPacker(dsr);

	// flac vars
	bool ok = true;
	FLAC::Encoder::File encoder;
	FLAC__StreamEncoderInitStatus init_status;
	FLAC__StreamMetadata *metadata[2];

	// setup the encoder
	if(!encoder) {
		fprintf(stderr, "ERROR: allocating encoder\n");
		return 0;
	}
	ok &= encoder.set_verify(true);
	ok &= encoder.set_compression_level(5);
	ok &= encoder.set_channels(dsr->getNumChannels());
	ok &= encoder.set_bits_per_sample(24);

	if ( dsr->getSamplingFreq() == 2822400 ) {
		ok &= encoder.set_sample_rate(176400);
	} else if ( dsr->getSamplingFreq() == 5644800 ) {
		ok &= encoder.set_sample_rate(352800);
	} else {
		fprintf(stderr, "ERROR: sample rate not supported by DoP\n");
		return 0;
	}
	ok &= encoder.set_total_samples_estimate((endPos - startPos)/16);

	// add tags and a padding block
	if(ok) {
		metadata[0] = id3v2_to_flac( id3tag );
		metadata[1] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING);
		metadata[1]->length = 2048; /* set the padding length */
		ok = encoder.set_metadata(metadata, 2);
	}

	// initialize encoder
	if(ok) {
		init_status = encoder.init(outpath.c_str());
		if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
			fprintf(stderr, "ERROR: initializing encoder: %s\n", FLAC__StreamEncoderInitStatusString[init_status]);
			ok = false;
		}
	}

	// return if there is a problem with any of the flac stuff.
	if (!ok)
		return ok;

	// creep up to the start point.
	while (dsr->getPosition() < startPos) {
		dsr->step();
	}
	// create a FLAC__int32 buffer to hold the samples as they are converted
	unsigned int bufferLen = dsr->getNumChannels()*flacBlockLen;
	FLAC__int32* buffer = new FLAC__int32[bufferLen];
	// MAIN CONVERSION LOOP //
	while (dsr->getPosition() <= endPos-flacBlockLen*16) {
		dopp.pack_buffer(buffer,bufferLen);
		if(!(ok = encoder.process_interleaved(buffer, flacBlockLen)))
			fprintf(stderr, "   state: %s\n", encoder.get_state().resolved_as_cstring(encoder));
		checkTimer(dsr->getPositionInSeconds(),dsr->getPositionAsPercent());
	}
	// delete the old buffer and make a new one with a single sample per chan
	delete[] buffer;
	buffer = new FLAC__int32[dsr->getNumChannels()];
	// creep up to the end
	while (dsr->getPosition() <= endPos) {
		dopp.pack_buffer(buffer,dsr->getNumChannels());
		if(!(ok = encoder.process_interleaved(buffer, 1)))
			fprintf(stderr, "   state: %s\n", encoder.get_state().resolved_as_cstring(encoder));
		checkTimer(dsr->getPositionInSeconds(),dsr->getPositionAsPercent());
	}
	delete[] buffer;
	// close the flac file
	ok &= encoder.finish();
	// report back to the user
	printf("\33[2K\r");
	printf("%3.1f%%\t",dsr->getPositionAsPercent());
	if (ok) {
		printf("Conversion completed sucessfully.\n");
	} else {
		printf("\nError during conversion.\n");
		fprintf(stderr, "encoding: %s\n", ok? "succeeded" : "FAILED");
		fprintf(stderr, "   state: %s\n", encoder.get_state().resolved_as_cstring(encoder));
	}
	// free things
	FLAC__metadata_object_delete(metadata[0]);
	FLAC__metadata_object_delete(metadata[1]);

	return ok;


	return ok;
}