示例#1
0
bool ExportOGG(AudacityProject *project,
               bool stereo, wxString fName,
               bool selectionOnly, double t0, double t1)
{
   double    rate    = project->GetRate();
   wxWindow  *parent = project;
   TrackList *tracks = project->GetTracks();
   double    quality = (gPrefs->Read("/FileFormats/OggExportQuality", 50)/(float)100.0);

   wxLogNull logNo;            // temporarily disable wxWindows error messages 
   bool      cancelling = false;

   wxFFile outFile(fName, "wb");

   if(!outFile.IsOpened()) {
      wxMessageBox(_("Unable to open target file for writing"));
      return false;
   }

   // All the Ogg and Vorbis encoding data
   ogg_stream_state stream;
   ogg_page         page;
   ogg_packet       packet;

   vorbis_info      info;
   vorbis_comment   comment;
   vorbis_dsp_state dsp;
   vorbis_block     block;

   // Encoding setup
   vorbis_info_init(&info);
   vorbis_encode_init_vbr(&info, stereo ? 2 : 1, int(rate + 0.5), quality);

   vorbis_comment_init(&comment);
   // If we wanted to add comments, we would do it here

   // Set up analysis state and auxiliary encoding storage
   vorbis_analysis_init(&dsp, &info);
   vorbis_block_init(&dsp, &block);

   // Set up packet->stream encoder.  According to encoder example,
   // a random serial number makes it more likely that you can make
   // chained streams with concatenation.
   srand(time(NULL));
   ogg_stream_init(&stream, rand());

   // First we need to write the required headers:
   //    1. The Ogg bitstream header, which contains codec setup params
   //    2. The Vorbis comment header
   //    3. The bitstream codebook.
   //
   // After we create those our responsibility is complete, libvorbis will
   // take care of any other ogg bistream constraints (again, according
   // to the example encoder source)
   ogg_packet bitstream_header;
   ogg_packet comment_header;
   ogg_packet codebook_header;

   vorbis_analysis_headerout(&dsp, &comment, &bitstream_header, &comment_header,
         &codebook_header);

   // Place these headers into the stream
   ogg_stream_packetin(&stream, &bitstream_header);
   ogg_stream_packetin(&stream, &comment_header);
   ogg_stream_packetin(&stream, &codebook_header);

   // Flushing these headers now guarentees that audio data will
   // start on a new page, which apparently makes streaming easier
   ogg_stream_flush(&stream, &page);
   outFile.Write(page.header, page.header_len);
   outFile.Write(page.body, page.body_len);

   double t = t0;
   bool   done = false;
   wxProgressDialog *progress = NULL;

   wxYield();
   wxStartTimer();

   while(!done && !cancelling){
      float       deltat = (float)SAMPLES_PER_RUN / rate;
      sampleCount samplesThisRun = SAMPLES_PER_RUN;
      Mixer       *mixer = new Mixer(stereo ? 2 : 1, SAMPLES_PER_RUN, 
            /* interleaved = */ false, rate, floatSample);

      if(t + deltat > t1) {
         done = true;
         deltat = t1 - t;
         samplesThisRun = int(deltat * rate + 0.5);
      }
      
      mixer->Clear();

      TrackListIterator iter(tracks);
      Track *tr = iter.First();
      while (tr) {
         if (tr->GetKind() == Track::Wave) {
            if (tr->GetSelected() || !selectionOnly) {
               if (tr->GetChannel() == Track::MonoChannel)
                  mixer->MixMono((WaveTrack *) tr, t, t + deltat);
               else if (tr->GetChannel() == Track::LeftChannel)
                  mixer->MixLeft((WaveTrack *) tr, t, t + deltat);
               else if (tr->GetChannel() == Track::RightChannel)
                  mixer->MixRight((WaveTrack *) tr, t, t + deltat);
            }
         }
         tr = iter.Next();
      }
      
      float **vorbis_buffer = vorbis_analysis_buffer(&dsp, SAMPLES_PER_RUN);
      
      float *left = (float *)mixer->GetBuffer(0);
      memcpy(vorbis_buffer[0], left, sizeof(float)*SAMPLES_PER_RUN);

      if(stereo) {
         float *right = (float *)mixer->GetBuffer(1);
         memcpy(vorbis_buffer[1], right, sizeof(float)*SAMPLES_PER_RUN);
      }

      // tell the encoder how many samples we have
      vorbis_analysis_wrote(&dsp, samplesThisRun);

      // I don't understand what this call does, so here is the comment
      // from the example, verbatim:
      //
      //    vorbis does some data preanalysis, then divvies up blocks
      //    for more involved (potentially parallel) processing. Get
      //    a single block for encoding now
      while(vorbis_analysis_blockout(&dsp, &block) == 1) {

         // analysis, assume we want to use bitrate management
         vorbis_analysis(&block, NULL);
         vorbis_bitrate_addblock(&block);

         while(vorbis_bitrate_flushpacket(&dsp, &packet)) {

            // add the packet to the bitstream
            ogg_stream_packetin(&stream, &packet);
            int result = ogg_stream_pageout(&stream, &page);

            if(result != 0) {
               outFile.Write(page.header, page.header_len);
               outFile.Write(page.body, page.body_len);
            }
         }
      }

      if(progress)
         cancelling = !progress->Update(int (((t - t0) * 1000) / (t1 - t0) + 0.5));
      else if(wxGetElapsedTime(false) > 500) {
            
         wxString message = selectionOnly ?
            _("Exporting the selected audio as Ogg Vorbis") :
            _("Exporting the entire project as Ogg Vorbis");

         progress = new wxProgressDialog(
               _("Export"),
               message,
               1000,
               parent,
               wxPD_CAN_ABORT | wxPD_REMAINING_TIME | wxPD_AUTO_HIDE);
      }

      delete mixer;
      t += deltat;
   }

   outFile.Close();

   if(progress)
      delete progress;

   return true;
}
示例#2
0
bool QuickMix(TrackList *tracks, DirManager *dirManager,
              double rate, sampleFormat format)
{
   WaveTrack **waveArray;
   VTrack *t;
   int numWaves = 0;
   int numLeft = 0;
   int numRight = 0;
   int numMono = 0;
   bool mono = false;
   int w;

   TrackListIterator iter(tracks);

   t = iter.First();
   while (t) {
      if (t->GetSelected() && t->GetKind() == VTrack::Wave) {
         numWaves++;
         switch (t->GetChannel()) {
         case VTrack::MonoChannel:
            numLeft++;
            numRight++;
            numMono++;
            break;
         case VTrack::LeftChannel:
            numLeft++;
            break;
         case VTrack::RightChannel:
            numRight++;
            break;
         }
      }
      t = iter.Next();
   }

   if (numMono == numWaves || numLeft == numWaves || numRight == numWaves)
      mono = true;

   double totalTime = 0.0;

   waveArray = new WaveTrack *[numWaves];
   w = 0;
   t = iter.First();
   while (t) {
      if (t->GetSelected() && t->GetKind() == VTrack::Wave) {
         waveArray[w++] = (WaveTrack *) t;
         if (t->GetMaxLen() > totalTime)
            totalTime = t->GetMaxLen();
      }
      t = iter.Next();
   }

   WaveTrack *mixLeft = new WaveTrack(dirManager);
   mixLeft->SetSampleFormat(format);
   mixLeft->SetRate(rate);
   mixLeft->SetChannel(VTrack::MonoChannel);
   mixLeft->SetName(_("Mix"));
   WaveTrack *mixRight = 0;
   if (!mono) {
      mixRight = new WaveTrack(dirManager);
      mixRight->SetSampleFormat(format);
      mixRight->SetRate(rate);
      mixRight->SetName(_("Mix"));
      mixLeft->SetChannel(VTrack::LeftChannel);
      mixRight->SetChannel(VTrack::RightChannel);
      mixLeft->SetLinked(true);
   }

   int maxBlockLen = mixLeft->GetIdealBlockSize();
   double maxBlockTime = maxBlockLen / mixLeft->GetRate();

   Mixer *mixer = new Mixer(mono ? 1 : 2, maxBlockLen, false,
                            rate, format);

   wxProgressDialog *progress = NULL;
   wxYield();
   wxStartTimer();
   wxBusyCursor busy;

   double tt = 0.0;
   while (tt < totalTime) {

      double blockTime = maxBlockTime;
      if (tt + blockTime > totalTime)
         blockTime = totalTime - tt;
      int blockLen = int (blockTime * mixLeft->GetRate());

      mixer->Clear();

      for (int i = 0; i < numWaves; i++) {
         if (mono)
            mixer->MixMono(waveArray[i], tt, tt + blockTime);
         else {
            switch (waveArray[i]->GetChannel()) {
            case VTrack::LeftChannel:
               mixer->MixLeft(waveArray[i], tt, tt + blockTime);
               break;
            case VTrack::RightChannel:
               mixer->MixRight(waveArray[i], tt, tt + blockTime);
               break;
            case VTrack::MonoChannel:
               mixer->MixMono(waveArray[i], tt, tt + blockTime);
               break;
            }
         }
      }

      if (mono) {
         samplePtr buffer = mixer->GetBuffer();
         mixLeft->Append(buffer, format, blockLen);
      } else {
         samplePtr buffer;
         buffer = mixer->GetBuffer(0);
         mixLeft->Append(buffer, format, blockLen);
         buffer = mixer->GetBuffer(1);
         mixRight->Append(buffer, format, blockLen);
      }

      tt += blockTime;

      if (!progress && wxGetElapsedTime(false) > 500) {
         progress =
             new wxProgressDialog(_("Quick Mix"), _("Mixing tracks"), 1000);
      }
      if (progress) {
         int progressvalue = int (1000 * (tt / totalTime));
         progress->Update(progressvalue);
      }
   }

   tracks->Add(mixLeft);
   if (!mono)
      tracks->Add(mixRight);

   delete progress;

   int elapsedMS = wxGetElapsedTime();
   double elapsedTime = elapsedMS * 0.001;
   double maxTracks = totalTime / (elapsedTime / numWaves);

#ifdef __WXGTK__
   printf(_("      Tracks: %d\n"), numWaves);
   printf(_("  Mix length: %f sec\n"), totalTime);
   printf(_("Elapsed time: %f sec\n"), elapsedTime);
   printf(_("Max number of tracks to mix in real time: %f\n"), maxTracks);
#endif

   delete waveArray;
   delete mixer;

   return true;
}
示例#3
0
bool ExportPCM(AudacityProject *project,
               wxString format, bool stereo, wxString fName,
               bool selectionOnly, double t0, double t1)
{
    wxMessageBox("In process of being rewritten, sorry...");

#if 0

    double rate = project->GetRate();
    wxWindow *parent = project;
    TrackList *tracks = project->GetTracks();

    int header = SND_HEAD_NONE;
#ifdef __WXMAC__
    bool trackMarkers = false;
#endif

    if (format == "WAV")
        header = SND_HEAD_WAVE;
    else if (format == "AIFF")
        header = SND_HEAD_AIFF;
    else if (format == "IRCAM")
        header = SND_HEAD_IRCAM;
    else if (format == "AU")
        header = SND_HEAD_NEXT;
#ifdef __WXMAC__
    else if (format == "AIFF with track markers") {
        header = SND_HEAD_AIFF;
        trackMarkers = true;
    }
#endif


    // Use snd library to export file

    snd_node sndfile;
    snd_node sndbuffer;

    sndfile.device = SND_DEVICE_FILE;
    sndfile.write_flag = SND_WRITE;
    strcpy(sndfile.u.file.filename, (const char *) fName);
    sndfile.u.file.file = 0;
    sndfile.u.file.header = header;
    sndfile.u.file.byte_offset = 0;
    sndfile.u.file.end_offset = 0;
    sndfile.u.file.swap = 0;
    sndfile.format.channels = stereo ? 2 : 1;
    sndfile.format.mode = SND_MODE_PCM;  // SND_MODE_FLOAT
    sndfile.format.bits = 16;
    sndfile.format.srate = int (rate + 0.5);

    int err;
    long flags = 0;

    err = snd_open(&sndfile, &flags);
    if (err) {
        wxMessageBox("Could not write to file.");
        return false;
    }

    sndbuffer.device = SND_DEVICE_MEM;
    sndbuffer.write_flag = SND_READ;
    sndbuffer.u.mem.buffer_max = 0;
    sndbuffer.u.mem.buffer = 0;
    sndbuffer.u.mem.buffer_len = 0;
    sndbuffer.u.mem.buffer_pos = 0;
    sndbuffer.format.channels = stereo ? 2 : 1;
    sndbuffer.format.mode = SND_MODE_PCM;        // SND_MODE_FLOAT
    sndbuffer.format.bits = 16;
    sndbuffer.format.srate = int (rate + 0.5);

    double timeStep = 10.0;      // write in blocks of 10 secs

    wxProgressDialog *progress = NULL;
    wxYield();
    wxStartTimer();
    wxBusyCursor busy;
    bool cancelling = false;

    double t = t0;

    while (t < t1 && !cancelling) {

        double deltat = timeStep;
        if (t + deltat > t1)
            deltat = t1 - t;

        sampleCount numSamples = int (deltat * rate + 0.5);

        Mixer *mixer = new Mixer(stereo ? 2 : 1, numSamples, true, rate);
        wxASSERT(mixer);
        mixer->Clear();

        char *buffer = new char[numSamples * 2 * sndbuffer.format.channels];
        wxASSERT(buffer);

        TrackListIterator iter(tracks);
        VTrack *tr = iter.First();
        while (tr) {
            if (tr->GetKind() == VTrack::Wave) {
                if (tr->selected || !selectionOnly) {
                    if (tr->channel == VTrack::MonoChannel)
                        mixer->MixMono((WaveTrack *) tr, t, t + deltat);
                    if (tr->channel == VTrack::LeftChannel)
                        mixer->MixLeft((WaveTrack *) tr, t, t + deltat);
                    if (tr->channel == VTrack::RightChannel)
                        mixer->MixRight((WaveTrack *) tr, t, t + deltat);
                }
            }
            tr = iter.Next();
        }

        sampleType *mixed = mixer->GetBuffer();

        long b2 = snd_convert(&sndfile, buffer,   // to
                              &sndbuffer, mixed, numSamples);     // from

        snd_write(&sndfile, buffer, b2);

        t += deltat;

        if (!progress && wxGetElapsedTime(false) > 500) {

            wxString message;

            if (selectionOnly)
                message =
                    wxString::
                    Format("Exporting the selected audio as a %s file",
                           (const char *) format);
            else
                message =
                    wxString::
                    Format("Exporting the entire project as a %s file",
                           (const char *) format);

            progress =
                new wxProgressDialog("Export",
                                     message,
                                     1000,
                                     parent,
                                     wxPD_CAN_ABORT |
                                     wxPD_REMAINING_TIME | wxPD_AUTO_HIDE);
        }
        if (progress) {
            cancelling =
                !progress->Update(int (((t - t0) * 1000) / (t1 - t0) + 0.5));
        }

        delete mixer;
        delete[]buffer;
    }

    snd_close(&sndfile);

#ifdef __WXMAC__

    FSSpec spec;

    wxMacFilename2FSSpec(fName, &spec);

    if (trackMarkers) {
        // Export the label track as "CD Spin Doctor" files

        LabelTrack *labels = NULL;
        TrackListIterator iter(tracks);
        VTrack *t = iter.First();
        while (t && !labels) {
            if (t->GetKind() == VTrack::Label)
                labels = (LabelTrack *) t;
            t = iter.Next();
        }
        if (labels) {
            FSpCreateResFile(&spec, 'AIFF', AUDACITY_CREATOR, 0);
            int resFile = FSpOpenResFile(&spec, fsWrPerm);
            if (resFile == -1) {
                int x = ResError();
            }
            if (resFile != -1) {
                UseResFile(resFile);

                int numLabels = labels->mLabels.Count();
                for (int i = 0; i < numLabels; i++) {
                    int startBlock = (int) (labels->mLabels[i]->t * 75);
                    int lenBlock;
                    if (i < numLabels - 1)
                        lenBlock =
                            (int) ((labels->mLabels[i + 1]->t -
                                    labels->mLabels[i]->t) * 75);
                    else
                        lenBlock =
                            (int) ((tracks->GetMaxLen() -
                                    labels->mLabels[i]->t) * 75);
                    int startSample = startBlock * 1176 + 54;
                    int lenSample = lenBlock * 1176 + 54;

                    Handle theHandle = NewHandle(50);
                    HLock(theHandle);
                    char *data = (char *) (*theHandle);
                    *(int *) &data[0] = startSample;
                    *(int *) &data[4] = lenSample;
                    *(int *) &data[8] = startBlock;
                    *(int *) &data[12] = lenBlock;
                    *(short *) &data[16] = i + 1;

                    wxString title = labels->mLabels[i]->title;
                    if (title.Length() > 31)
                        title = title.Left(31);
                    data[18] = title.Length();
                    strcpy(&data[19], (const char *) title);

                    HUnlock(theHandle);
                    AddResource(theHandle, 'SdCv', 128 + i, "\p");
                }
                CloseResFile(resFile);

                wxMessageBox("Saved track information with file.");
            }
        }
    }

    FInfo finfo;
    if (FSpGetFInfo(&spec, &finfo) == noErr) {
        switch (header) {
        case SND_HEAD_AIFF:
            finfo.fdType = 'AIFF';
            break;
        case SND_HEAD_IRCAM:
            finfo.fdType = 'IRCA';
            break;
        case SND_HEAD_NEXT:
            finfo.fdType = 'AU  ';
            break;
        case SND_HEAD_WAVE:
            finfo.fdType = 'WAVE';
            break;
        }

        finfo.fdCreator = AUDACITY_CREATOR;

        FSpSetFInfo(&spec, &finfo);
    }
#endif

    if (progress)
        delete progress;

    return true;

#endif

    return false;

}
示例#4
0
bool ExportCL(AudacityProject *project, bool stereo, wxString fName,
              bool selectionOnly, double t0, double t1)
{
   int rate = int(project->GetRate() + 0.5);
   wxWindow *parent = project;
   TrackList *tracks = project->GetTracks();
   
   wxString command = gPrefs->Read("/FileFormats/ExternalProgramExportCommand", "lame - '%f'");
   command.Replace("%f", fName);

   /* establish parameters */
   int channels = stereo ? 2 : 1;
   unsigned long totalSamples = (unsigned long)((t1 - t0) * rate + 0.5);
   unsigned long sampleBytes = totalSamples * channels * SAMPLE_SIZE(int16Sample);
   double timeStep = 10.0;      // write in blocks of 10 secs

   /* fill up the wav header */
   wav_header header;
   header.riffID[0] = 'R';
   header.riffID[1] = 'I';
   header.riffID[2] = 'F';
   header.riffID[3] = 'F';
   header.riffType[0] = 'W';
   header.riffType[1] = 'A';
   header.riffType[2] = 'V';
   header.riffType[3] = 'E';
   header.lenAfterRiff = sampleBytes + 32;

   header.fmtID[0]  = 'f';
   header.fmtID[1]  = 'm';
   header.fmtID[2]  = 't';
   header.fmtID[3]  = ' ';
   header.formatChunkLen = 16;
   header.formatTag      = 1;
   header.channels       = channels;
   header.sampleRate     = rate;
   header.bitsPerSample  = SAMPLE_SIZE(int16Sample) * 8;
   header.blockAlign     = header.bitsPerSample * header.channels;
   header.avgBytesPerSec = header.sampleRate * header.blockAlign;

   header.dataID[0] = 'd';
   header.dataID[1] = 'a';
   header.dataID[2] = 't';
   header.dataID[3] = 'a';
   header.dataLen   = sampleBytes;

   FILE *pipe = popen(command.c_str(), "w");

   /* write the header */

   fwrite( &header, sizeof(wav_header), 1, pipe );

   //sampleCount maxSamples = int (timeStep * rate + 0.5);

   wxProgressDialog *progress = NULL;
   wxYield();
   wxStartTimer();
   wxBusyCursor busy;
   bool cancelling = false;

   double t = t0;

   while (t < t1 && !cancelling) {

      double deltat = timeStep;
      if (t + deltat > t1)
         deltat = t1 - t;

      sampleCount numSamples = int (deltat * rate + 0.5);

      Mixer *mixer = new Mixer(channels, numSamples, true, rate, int16Sample);
      wxASSERT(mixer);
      mixer->Clear();

      char *buffer = new char[numSamples * SAMPLE_SIZE(int16Sample) * channels];
      wxASSERT(buffer);

      TrackListIterator iter(tracks);
      VTrack *tr = iter.First();
      while (tr) {
         if (tr->GetKind() == VTrack::Wave) {
            if (tr->GetSelected() || !selectionOnly) {
               if (tr->GetChannel() == VTrack::MonoChannel)
                  mixer->MixMono((WaveTrack *) tr, t, t + deltat);
               if (tr->GetChannel() == VTrack::LeftChannel)
                  mixer->MixLeft((WaveTrack *) tr, t, t + deltat);
               if (tr->GetChannel() == VTrack::RightChannel)
                  mixer->MixRight((WaveTrack *) tr, t, t + deltat);
            }
         }
         tr = iter.Next();
      }

      samplePtr mixed = mixer->GetBuffer();

      // Byte-swapping is neccesary on big-endian machines, since
      // WAV files are little-endian
#if wxBYTE_ORDER == wxBIG_ENDIAN
      {
         short *buffer = (short*)mixed;
         for( int i = 0; i < numSamples; i++ )
            buffer[i] = wxINT16_SWAP_ON_BE(buffer[i]);
      }
#endif

      fwrite( mixed, numSamples * channels * SAMPLE_SIZE(int16Sample), 1, pipe );

      t += deltat;

      if (!progress && wxGetElapsedTime(false) > 500) {

         wxString message;

         if (selectionOnly)
            message = "Exporting the selected audio using command-line encoder";
         else
            message = "Exporting the entire project using command-line encoder";

         progress =
             new wxProgressDialog("Export",
                                  message,
                                  1000,
                                  parent,
                                  wxPD_CAN_ABORT |
                                  wxPD_REMAINING_TIME | wxPD_AUTO_HIDE);
      }
      if (progress) {
         cancelling =
             !progress->Update(int (((t - t0) * 1000) / (t1 - t0) + 0.5));
      }

      delete mixer;
      delete[]buffer;
   }

   pclose( pipe );

   if(progress)
      delete progress;
   return true;
}
示例#5
0
bool ExportMP3(AudacityProject *project,
               bool stereo, wxString fName,
               bool selectionOnly, double t0, double t1)
{
   double rate = project->GetRate();
   wxWindow *parent = project;
   TrackList *tracks = project->GetTracks();

   wxLogNull logNo;             /* temporarily disable wxWindows error messages */

   bool success = GetMP3Exporter()->FindLibrary(parent);
   
   if (!success)
      return false;

   success = GetMP3Exporter()->LoadLibrary();
   if (!success) {
      wxMessageBox(_("Could not open MP3 encoding library!"));
      gPrefs->Write("/MP3/MP3LibPath", wxString(""));

      return false;
   }

   if(!GetMP3Exporter()->ValidLibraryLoaded()) {
      wxMessageBox(_("Not a valid or supported MP3 encoding library!"));      
      gPrefs->Write("/MP3/MP3LibPath", wxString(""));
      
      return false;
   }
   
   /* Open file for writing */

   wxFFile outFile(fName, "wb");
   if (!outFile.IsOpened()) {
      wxMessageBox(_("Unable to open target file for writing"));
      return false;
   }
   
   /* Put ID3 tags at beginning of file */
   
   Tags *tags = project->GetTags();
   if (!tags->ShowEditDialog(project, _("Edit the ID3 tags for the MP3 file")))
      return false;  // used selected "cancel"

   char *id3buffer;
   int id3len;
   bool endOfFile;
   id3len = tags->ExportID3(&id3buffer, &endOfFile);
   if (!endOfFile)
     outFile.Write(id3buffer, id3len);

   /* Export MP3 using DLL */

   long bitrate = gPrefs->Read("/FileFormats/MP3Bitrate", 128);
   GetMP3Exporter()->SetBitrate(bitrate);

   sampleCount inSamples = GetMP3Exporter()->InitializeStream(stereo ? 2 : 1, int(rate + 0.5));
   double timeStep =  (double)inSamples / rate;
   double t = t0;

   wxProgressDialog *progress = NULL;
   wxYield();
   wxStartTimer();
   wxBusyCursor busy;
   bool cancelling = false;
   long bytes;


   int bufferSize = GetMP3Exporter()->GetOutBufferSize();
   unsigned char *buffer = new unsigned char[bufferSize];
   wxASSERT(buffer);

   while (t < t1 && !cancelling) {

      double deltat = timeStep;
      bool lastFrame = false;
      sampleCount numSamples = inSamples;

      if (t + deltat > t1) {
         lastFrame = true;
         deltat = t1 - t;
         numSamples = int(deltat * rate + 0.5);
      }


      Mixer *mixer = new Mixer(stereo ? 2 : 1, numSamples, true,
                               rate, int16Sample);
      wxASSERT(mixer);
      mixer->Clear();


      TrackListIterator iter(tracks);
      VTrack *tr = iter.First();
      while (tr) {
         if (tr->GetKind() == VTrack::Wave) {
            if (tr->GetSelected() || !selectionOnly) {
               if (tr->GetChannel() == VTrack::MonoChannel)
                  mixer->MixMono((WaveTrack *) tr, t, t + deltat);
               else if (tr->GetChannel() == VTrack::LeftChannel)
                  mixer->MixLeft((WaveTrack *) tr, t, t + deltat);
               else if (tr->GetChannel() == VTrack::RightChannel)
                  mixer->MixRight((WaveTrack *) tr, t, t + deltat);
            }
         }
         tr = iter.Next();
      }
      
      short *mixed = (short *)mixer->GetBuffer();

      if(lastFrame)
         bytes = GetMP3Exporter()->EncodeRemainder(mixed, numSamples, buffer);
      else
         bytes = GetMP3Exporter()->EncodeBuffer(mixed, buffer);

      outFile.Write(buffer, bytes);

      t += deltat;

      if (!progress && wxGetElapsedTime(false) > 500) {

         wxString message;

         if (selectionOnly)
            message =
                wxString::Format(_("Exporting the selected audio as an mp3"));
         else
            message =
                wxString::Format(_("Exporting the entire project as an mp3"));

         progress =
             new wxProgressDialog(_("Export"),
                                  message,
                                  1000,
                                  parent,
                                  wxPD_CAN_ABORT |
                                  wxPD_REMAINING_TIME | wxPD_AUTO_HIDE);
      }

      if (progress) {
         cancelling =
             !progress->Update(int (((t - t0) * 1000) / (t1 - t0) + 0.5));
      }

      delete mixer;

   }

   bytes = GetMP3Exporter()->FinishStream(buffer);

   if (bytes)
      outFile.Write(buffer, bytes);
   
   /* Write ID3 tag if it was supposed to be at the end of the file */
   
   if (endOfFile)
      outFile.Write(id3buffer, id3len);
   delete[] id3buffer;

   /* Close file */
   
   outFile.Close();
      
   /* MacOS: set the file type/creator so that the OS knows it's an MP3
      file which was created by Audacity */
      
#ifdef __WXMAC__
   FSSpec spec;
   wxMacFilename2FSSpec(fName, &spec);
   FInfo finfo;
   if (FSpGetFInfo(&spec, &finfo) == noErr) {
      finfo.fdType = 'MP3 ';
      finfo.fdCreator = AUDACITY_CREATOR;

      FSpSetFInfo(&spec, &finfo);
   }
#endif

   if (progress)
      delete progress;

   delete[]buffer;
   
   return true;
}
示例#6
0
bool ExportPCM(AudacityProject *project,
               bool stereo, wxString fName,
               bool selectionOnly, double t0, double t1)
{
   double       rate = project->GetRate();
   wxWindow    *parent = project;
   TrackList   *tracks = project->GetTracks();
   int          format = ReadExportFormatPref();
   int          formatBits = ReadExportFormatBitsPref();
   wxString     formatStr;
   SF_INFO      info;
   SNDFILE     *sf;
   int          err;

   formatStr = sf_header_name(format & SF_FORMAT_TYPEMASK);

   // Use libsndfile to export file

   info.samplerate = (unsigned int)(rate + 0.5);
   info.samples = (unsigned int)((t1 - t0)*rate + 0.5);
   info.channels = stereo? 2: 1;
   info.pcmbitwidth = formatBits;
   info.format = format;
   info.sections = 1;
   info.seekable = 0;

   // If we can't export exactly the format they requested,
   // try the default format for that header type, and try
   // 16-bit samples.
   if (!sf_format_check(&info))
      info.format = (info.format & SF_FORMAT_TYPEMASK);
   if (!sf_format_check(&info))
      info.pcmbitwidth = 16;
   if (!sf_format_check(&info)) {
      wxMessageBox(_("Cannot export audio in this format."));
      return false;
   }

   sf = sf_open_write((const char *)fName, &info);
   if (!sf) {
      wxMessageBox(wxString::Format(_("Cannot export audio to %s"),
                                    (const char *)fName));
      return false;
   }

   double timeStep = 10.0;      // write in blocks of 10 secs

   wxProgressDialog *progress = NULL;
   wxYield();
   wxStartTimer();
   wxBusyCursor busy;
   bool cancelling = false;

   double t = t0;

   while (t < t1 && !cancelling) {

      double deltat = timeStep;
      if (t + deltat > t1)
         deltat = t1 - t;

      sampleCount numSamples = int (deltat * rate + 0.5);

      Mixer *mixer = new Mixer(stereo ? 2 : 1, numSamples, true, rate);
      wxASSERT(mixer);
      mixer->Clear();

      TrackListIterator iter(tracks);
      VTrack *tr = iter.First();
      while (tr) {
         if (tr->GetKind() == VTrack::Wave) {
            if (tr->GetSelected() || !selectionOnly) {
               if (tr->GetChannel() == VTrack::MonoChannel)
                  mixer->MixMono((WaveTrack *) tr, t, t + deltat);
               if (tr->GetChannel() == VTrack::LeftChannel)
                  mixer->MixLeft((WaveTrack *) tr, t, t + deltat);
               if (tr->GetChannel() == VTrack::RightChannel)
                  mixer->MixRight((WaveTrack *) tr, t, t + deltat);
            }
         }
         tr = iter.Next();
      }

      sampleType *mixed = mixer->GetBuffer();

      sf_writef_short(sf, mixed, numSamples);

      t += deltat;

      if (!progress && wxGetElapsedTime(false) > 500) {

         wxString message;

         if (selectionOnly)
            message =
                wxString::
                Format(_("Exporting the selected audio as a %s file"),
                       (const char *) formatStr);
         else
            message =
                wxString::
                Format(_("Exporting the entire project as a %s file"),
                       (const char *) formatStr);

         progress =
             new wxProgressDialog(_("Export"),
                                  message,
                                  1000,
                                  parent,
                                  wxPD_CAN_ABORT |
                                  wxPD_REMAINING_TIME | wxPD_AUTO_HIDE);
      }
      if (progress) {
         cancelling =
             !progress->Update(int (((t - t0) * 1000) / (t1 - t0) + 0.5));
      }

      delete mixer;
   }

   err = sf_close(sf);

   if (err) {
      char buffer[1000];
      sf_error_str(sf, buffer, 1000);
      wxMessageBox(wxString::Format
                   (_("Error (file may not have been written): %s"),
                    buffer));
   }

#ifdef __WXMAC__

   FSSpec spec;

   wxMacFilename2FSSpec(fName, &spec);

   FInfo finfo;
   if (FSpGetFInfo(&spec, &finfo) == noErr) {
      finfo.fdType = sf_header_mactype(format & SF_FORMAT_TYPEMASK);
      finfo.fdCreator = AUDACITY_CREATOR;

      FSpSetFInfo(&spec, &finfo);
   }
#endif

   if (progress)
      delete progress;

   return true;
}
示例#7
0
void AudioIO::FillBuffers()
{
   unsigned int numEmpty = 0;
   unsigned int i;
   
   // Playback buffers

   for(i=0; i<mNumOutBuffers; i++) {
      if (mOutBuffer[i].ID == 0)
         numEmpty++;
   }
   
   if (numEmpty > (mNumOutBuffers/2)) {
      sampleCount block = numEmpty * mBufferSize;   
      double deltat = block / mRate;
      if (mT + deltat > mT1) {
         deltat = mT1 - mT;
         if(deltat < 0.0) return;
         block = (sampleCount)(deltat * mRate + 0.5);
      }
      
      Mixer *mixer = new Mixer(mNumOutChannels, block, true,
                               mRate, mFormat);
      mixer->UseVolumeSlider(mProject->GetControlToolBar());

      mixer->Clear();

      TrackListIterator iter2(mTracks);
      int numSolo = 0;
      Track *vt = iter2.First();
      while (vt) {
         if (vt->GetKind() == Track::Wave && vt->GetSolo())
            numSolo++;
         vt = iter2.Next();
      }

      TrackListIterator iter(mTracks);
      vt = iter.First();
      while (vt) {
         if (vt->GetKind() == Track::Wave) {      

            Track *mt = vt;
         
            // We want to extract mute and solo information from
            // the top of the two tracks if they're linked
            // (i.e. a stereo pair only has one set of mute/solo buttons)
            Track *partner = mTracks->GetLink(vt);
            if (partner && !vt->GetLinked())
               mt = partner;
            else
               mt = vt;

            // Cut if somebody else is soloing
            if (numSolo>0 && !mt->GetSolo()) {
               vt = iter.Next();
               continue;
            }
            
            // Cut if we're muted (unless we're soloing)
            if (mt->GetMute() && !mt->GetSolo()) {
               vt = iter.Next();
               continue;
            }

            WaveTrack *t = (WaveTrack *) vt;
            
            switch (t->GetChannel()) {
            case Track::LeftChannel:
               mixer->MixLeft(t, mT, mT + deltat);
               break;
            case Track::RightChannel:
               mixer->MixRight(t, mT, mT + deltat);
               break;
            case Track::MonoChannel:
               mixer->MixMono(t, mT, mT + deltat);
               break;
            }
         }

         vt = iter.Next();
      }     
   
      // Copy the mixed samples into the buffers

      samplePtr outbytes = mixer->GetBuffer();   

      for(i=0; i<mNumOutBuffers && block>0; i++)
         if (mOutBuffer[i].ID == 0) {
            sampleCount count;
            if (block > mBufferSize)
               count = mBufferSize;
            else
               count = block;
            
            memcpy(mOutBuffer[i].data, outbytes,
                   count*mNumOutChannels*SAMPLE_SIZE(mFormat));
            block -= count;
            outbytes += (count*mNumOutChannels*SAMPLE_SIZE(mFormat));
            mOutBuffer[i].len = count;
            mOutBuffer[i].ID = mOutID;
            mOutID++;
         }

      delete mixer;

      mT += deltat;
   }
   
   // Recording buffers
   
   unsigned int numFull = 0;
   unsigned int f, c; // loop counters
   sampleCount flatLen;
      
   for(i=0; i<mNumInBuffers; i++) {
      if (mInBuffer[i].ID != 0)
         numFull++;
   }
   
   if (numFull > 8) {
   
      samplePtr *flat = new samplePtr[mNumInChannels];
      for(i=0; i<mNumInChannels; i++)
         flat[i] = NewSamples(numFull * mBufferSize, mFormat);
      
      flatLen = 0;
      for(f=0; f<numFull; f++) {
         int minID = mInID+1;
         int minIndex = 0;
         for(i=0; i<mNumInBuffers; i++)
            if (mInBuffer[i].ID > 0 &&
                mInBuffer[i].ID < minID) {
               minIndex = i;
               minID = mInBuffer[i].ID;
            }

         switch(mFormat) {
         case floatSample:
            int j;
            for(j=0; j<mInBuffer[minIndex].len; j++)
               for(c=0; c<mNumInChannels; c++) {
                  ((float *)flat[c])[flatLen+j] =
                     ((float *)mInBuffer[minIndex].data)[j*mNumInChannels + c];
               }
            break;
         default:
            wxASSERT(0);
         }

         flatLen += mInBuffer[minIndex].len;
         mInBuffer[minIndex].ID = 0;
      }
      
      for(i=0; i<mNumInChannels; i++)
         mInTracks[i]->Append(flat[i], mFormat, flatLen);

      for(i=0; i<mNumInChannels; i++)
         DeleteSamples(flat[i]);
      delete[] flat;

      mProject->RedrawProject();
   }
}