void TranscriptionToolBar::OnEndOff(wxCommandEvent & WXUNUSED(event)) { //If IO is busy, abort immediately if (gAudioIO->IsBusy()){ SetButton(false,mButtons[TTB_EndOff]); return; } mVk->AdjustThreshold(GetSensitivity()); AudacityProject *p = GetActiveProject(); auto t = *p->GetTracks()->Any< const WaveTrack >().begin(); if(t) { auto wt = static_cast<const WaveTrack*>(t); sampleCount start, len; GetSamples(wt, &start, &len); //Adjust length to end if selection is null if(len == 0) { len = start; start = 0; } auto newEnd = mVk->OffBackward(*wt, start + len, len); double newpos = newEnd.as_double() / wt->GetRate(); p->SetSel1(newpos); p->RedrawProject(); SetButton(false, mButtons[TTB_EndOff]); } }
void TranscriptionToolBar::OnEndOn(wxCommandEvent & WXUNUSED(event)) { //If IO is busy, abort immediately if (gAudioIO->IsBusy()){ SetButton(false,mButtons[TTB_EndOn]); return; } mVk->AdjustThreshold(GetSensitivity()); AudacityProject *p = GetActiveProject(); TrackList *tl = p->GetTracks(); TrackListOfKindIterator iter(Track::Wave, tl); Track *t = iter.First(); //Make a track if(t) { sampleCount start,len; GetSamples((WaveTrack*)t, &start,&len); //Adjust length to end if selection is null if(len == 0) { len = start; start = 0; } sampleCount newEnd = mVk->OnBackward(*(WaveTrack*)t,start+ len,len); double newpos = newEnd / ((WaveTrack*)t)->GetRate(); p->SetSel1(newpos); p->RedrawProject(); SetButton(false, mButtons[TTB_EndOn]); } }
void TranscriptionToolBar::OnStartOff(wxCommandEvent & WXUNUSED(event)) { //If IO is busy, abort immediately if (gAudioIO->IsBusy()){ SetButton(false,mButtons[TTB_StartOff]); return; } mVk->AdjustThreshold(GetSensitivity()); AudacityProject *p = GetActiveProject(); TrackList *tl = p->GetTracks(); TrackListOfKindIterator iter(Track::Wave, tl); SetButton(false, mButtons[TTB_StartOff]); Track *t = iter.First(); //Make a track if(t) { auto wt = static_cast<const WaveTrack*>(t); sampleCount start, len; GetSamples(wt, &start, &len); //Adjust length to end if selection is null //if(len == 0) //len = wt->GetSequence()->GetNumSamples()-start; auto newstart = mVk->OffForward(*wt, start, len); double newpos = newstart.as_double() / wt->GetRate(); p->SetSel0(newpos); p->RedrawProject(); SetButton(false, mButtons[TTB_StartOn]); } }
//----------------------------------------------------------------------- Duration AudioClip::Length() const { POMDOG_ASSERT(nativeAudioClip); auto samples = GetSamples(nativeAudioClip->SizeInBytes(), bitsPerSample, channels); auto sampleDuration = GetSampleDuration(samples, sampleRate); return std::move(sampleDuration); }
void TranscriptionToolBar::OnStartOff(wxCommandEvent & WXUNUSED(event)) { //If IO is busy, abort immediately if (gAudioIO->IsBusy()){ SetButton(false,mButtons[TTB_StartOff]); return; } mVk->AdjustThreshold(GetSensitivity()); AudacityProject *p = GetActiveProject(); SetButton(false, mButtons[TTB_StartOff]); auto t = *p->GetTracks()->Any< const WaveTrack >().begin(); if(t) { auto wt = static_cast<const WaveTrack*>(t); sampleCount start, len; GetSamples(wt, &start, &len); //Adjust length to end if selection is null //if(len == 0) //len = wt->GetSequence()->GetNumSamples()-start; auto newstart = mVk->OffForward(*wt, start, len); double newpos = newstart.as_double() / wt->GetRate(); auto &selectedRegion = p->GetViewInfo().selectedRegion; selectedRegion.setT0( newpos ); p->RedrawProject(); SetButton(false, mButtons[TTB_StartOn]); } }
Var* ff_fft(vfuncptr func, Var* arg) { Var *real = NULL, *img = NULL; double* data; int i, j, n, x, y, z; COMPLEX *in, *out; Alist alist[4]; alist[0] = make_alist("real", ID_VAL, NULL, &real); alist[1] = make_alist("img", ID_VAL, NULL, &img); alist[2].name = NULL; if (parse_args(func, arg, alist) == 0) return (NULL); if (real == NULL && img == NULL) { parse_error("%s: No real or imaginary objects specified\n", func->name); return (NULL); } x = GetSamples(V_SIZE(real), V_ORG(real)); y = GetLines(V_SIZE(real), V_ORG(real)); z = GetBands(V_SIZE(real), V_ORG(real)); if (img == NULL && x == 2) { n = y * z; in = (COMPLEX*)calloc(n, sizeof(COMPLEX)); out = (COMPLEX*)calloc(n, sizeof(COMPLEX)); for (i = 0; i < y; i++) { for (j = 0; j < z; j++) { in[i].re = extract_double(real, cpos(0, i, j, real)); in[i].im = extract_double(real, cpos(1, i, j, real)); } } } else { n = V_DSIZE(real); in = (COMPLEX*)calloc(n, sizeof(COMPLEX)); out = (COMPLEX*)calloc(n, sizeof(COMPLEX)); for (i = 0; i < n; i++) { in[i].re = extract_double(real, i); in[i].im = (img == NULL ? 0.0 : extract_double(img, i)); } } if (func->fdata == (void*)1) { fft(in, n, out); } else { rft(in, n, out); } data = (double*)calloc(n * 2, sizeof(double)); for (i = 0; i < n; i++) { data[i * 2] = out[i].re; data[i * 2 + 1] = out[i].im; } return (newVal(BSQ, 2, n, 1, DV_DOUBLE, data)); }
bool VSTEffect::Init() { if (!mAEffect) { Load(); } if (!mAEffect) { return false; } mBlockSize = 0; TrackListIterator iter(mOutputTracks); WaveTrack *left = (WaveTrack *) iter.First(); while (left) { sampleCount lstart; sampleCount llen; GetSamples(left, &lstart, &llen); if (left->GetLinked()) { WaveTrack *right = (WaveTrack *) iter.Next(); sampleCount rstart; sampleCount rlen; GetSamples(right, &rstart, &rlen); if (left->GetRate() != right->GetRate()) { wxMessageBox(_("Both channels of a stereo track must be the same sample rate.")); return false; } if (llen != rlen) { wxMessageBox(_("Both channels of a stereo track must be the same length.")); return false; } } left = (WaveTrack *) iter.Next(); } return true; }
bool LadspaEffect::Process() { this->CopyInputWaveTracks(); // Set up mOutputWaveTracks. bool bGoodResult = true; TrackListIterator iter(mOutputWaveTracks); int count = 0; Track *left = iter.First(); Track *right; while(left) { sampleCount lstart = 0, rstart = 0; sampleCount len; GetSamples((WaveTrack *)left, &lstart, &len); right = NULL; if (left->GetLinked() && inputs>1) { right = iter.Next(); GetSamples((WaveTrack *)right, &rstart, &len); } if (inputs < 2 && right) { // If the effect is mono, apply to each channel separately bGoodResult = ProcessStereo(count, (WaveTrack *)left, NULL, lstart, 0, len) && ProcessStereo(count, (WaveTrack *)right, NULL, rstart, 0, len); } else bGoodResult = ProcessStereo(count, (WaveTrack *)left, (WaveTrack *)right, lstart, rstart, len); if (!bGoodResult) break; left = iter.Next(); count++; } this->ReplaceProcessedWaveTracks(bGoodResult); return bGoodResult; }
bool LadspaEffect::Process() { TrackListIterator iter(mWaveTracks); int count = 0; Track *left = iter.First(); Track *right; while(left) { longSampleCount lstart, rstart; sampleCount len; GetSamples((WaveTrack *)left, &lstart, &len); right = NULL; if (left->GetLinked() && inputs>1) { right = iter.Next(); GetSamples((WaveTrack *)right, &rstart, &len); } bool success = false; if (inputs < 2 && right) { // If the effect is mono, apply to each channel separately success = ProcessStereo(count, (WaveTrack *)left, NULL, lstart, 0, len); if (success) success = ProcessStereo(count, (WaveTrack *)right, NULL, rstart, 0, len); } else success = ProcessStereo(count, (WaveTrack *)left, (WaveTrack *)right, lstart, rstart, len); if (!success) return false; left = iter.Next(); count++; } return true; }
bool LadspaEffect::Init() { mBlockSize = 0; mainRate = 0; TrackListIterator iter(mWaveTracks); VTrack *left = iter.First(); while(left) { sampleCount lstart, rstart, llen, rlen; GetSamples((WaveTrack *)left, &lstart, &llen); if (mainRate == 0) mainRate = (int)(((WaveTrack *)left)->GetRate() + 0.5); if (left->GetLinked()) { VTrack *right = iter.Next(); GetSamples((WaveTrack *)right, &rstart, &rlen); if (llen != rlen || ((WaveTrack *)left)->GetRate() != ((WaveTrack *)right)->GetRate()) { wxMessageBox(_("Sorry, Ladspa Effects cannot be performed " "on stereo tracks where the individual " "channels of the track do not match.")); return false; } } left = iter.Next(); } if (mainRate<=0) mainRate = 44100; return true; }
bool AllegroSoundSample5::Load( const std::string & path ) { if ( m_pInstance ) { al_detach_sample_instance( m_pInstance ); al_destroy_sample_instance( m_pInstance ); } SamplePtr pSampleData = GetSamples().Load( path ); if ( !pSampleData || !pSampleData->m_pSample ) return false; m_pInstance = al_create_sample_instance( pSampleData->m_pSample ); al_attach_sample_instance_to_mixer( m_pInstance, ((AllegroSound5&)GetSound()).GetSoundMixer() ); return ( m_pInstance != 0 ); }
void TranscriptionToolBar::OnCalibrate(wxCommandEvent & WXUNUSED(event)) { //If IO is busy, abort immediately if (gAudioIO->IsBusy()){ SetButton(false,mButtons[TTB_Calibrate]); return; } AudacityProject *p = GetActiveProject(); TrackList *tl = p->GetTracks(); TrackListOfKindIterator iter(Track::Wave, tl); Track *t = iter.First(); //Get a track if(t) { auto wt = static_cast<const WaveTrack*>(t); sampleCount start, len; GetSamples(wt, &start, &len); mVk->CalibrateNoise(*wt, start, len); mVk->AdjustThreshold(3); mButtons[TTB_StartOn]->Enable(); mButtons[TTB_StartOff]->Enable(); mButtons[TTB_EndOn]->Enable(); mButtons[TTB_EndOff]->Enable(); //mThresholdSensitivity->Set(3); SetButton(false,mButtons[TTB_Calibrate]); } mButtons[TTB_StartOn]->Enable(); mButtons[TTB_StartOff]->Enable(); mButtons[TTB_EndOn]->Enable(); mButtons[TTB_EndOff]->Enable(); mButtons[TTB_SelectSound]->Enable(); mButtons[TTB_SelectSilence]->Enable(); mButtons[TTB_AutomateSelection]->Enable(); //Make the sensititivy slider set the sensitivity by processing an event. wxCommandEvent dummy; OnSensitivitySlider(dummy); }
bool EffectFilter::Process() { TrackListIterator iter(mWaveTracks); VTrack *t = iter.First(); int count = 0; while(t) { sampleCount start, len; GetSamples((WaveTrack *)t, &start, &len); bool success = ProcessOne(count, (WaveTrack *)t, start, len); if (!success) return false; t = iter.Next(); count++; } return true; }
void TranscriptionToolBar::OnSelectSound(wxCommandEvent & WXUNUSED(event)) { //If IO is busy, abort immediately if (gAudioIO->IsBusy()){ SetButton(false,mButtons[TTB_SelectSound]); return; } mVk->AdjustThreshold(GetSensitivity()); AudacityProject *p = GetActiveProject(); TrackList *tl = p->GetTracks(); TrackListIterator iter(tl); Track *t = iter.First(); //Make a track if(t) { sampleCount start,len; GetSamples((WaveTrack*)t, &start,&len); //Adjust length to end if selection is null //if(len == 0) //len = (WaveTrack*)t->GetSequence()->GetNumSamples()-start; double rate = ((WaveTrack*)t)->GetRate(); sampleCount newstart = mVk->OffBackward(*(WaveTrack*)t,start,start); sampleCount newend = mVk->OffForward(*(WaveTrack*)t,start+len,(int)(tl->GetEndTime()*rate)); //reset the selection bounds. p->SetSel0(newstart / rate); p->SetSel1(newend / rate); p->RedrawProject(); } SetButton(false,mButtons[TTB_SelectSound]); }
void TranscriptionToolBar::OnSelectSound(wxCommandEvent & WXUNUSED(event)) { //If IO is busy, abort immediately if (gAudioIO->IsBusy()){ SetButton(false,mButtons[TTB_SelectSound]); return; } mVk->AdjustThreshold(GetSensitivity()); AudacityProject *p = GetActiveProject(); TrackList *tl = p->GetTracks(); if(auto wt = *tl->Any<const WaveTrack>().begin()) { sampleCount start, len; GetSamples(wt, &start, &len); //Adjust length to end if selection is null //if(len == 0) //len = wt->GetSequence()->GetNumSamples()-start; double rate = wt->GetRate(); auto newstart = mVk->OffBackward(*wt, start, start); auto newend = mVk->OffForward(*wt, start + len, (int)(tl->GetEndTime() * rate)); //reset the selection bounds. auto &selectedRegion = p->GetViewInfo().selectedRegion; selectedRegion.setTimes( newstart.as_double() / rate, newend.as_double() / rate ); p->RedrawProject(); } SetButton(false,mButtons[TTB_SelectSound]); }
bool EffectNoiseRemoval::Process() { if (doProfile) { for(int i=0; i<windowSize; i++) { sum[i] = 0.0; sumsq[i] = 0.0; profileCount[i] = 0; } } TrackListIterator iter(mWaveTracks); VTrack *t = iter.First(); int count = 0; while(t) { sampleCount start, len; GetSamples((WaveTrack *)t, &start, &len); bool success = ProcessOne(count, (WaveTrack *)t, start, len); if (!success) return false; t = iter.Next(); count++; } if (doProfile) { for(int i=0; i<=windowSize/2; i++) { float avg = sum[i] / profileCount[i]; float stddev = sqrt(sumsq[i] - (sum[i]*sum[i])/profileCount[i]) / profileCount[i]; noiseGate[i] = avg; } hasProfile = true; } return true; }
bool EffectAmplify::Init() { peak = 0.0; TrackListIterator iter(mWaveTracks); VTrack *t = iter.First(); int count = 0; while(t) { sampleCount start, len; sampleType min, max; GetSamples((WaveTrack *)t, &start, &len); ((WaveTrack *)t)->GetMinMax(start, len, &min, &max); float newpeak = (abs(min) > abs(max) ? abs(min) : abs(max)) / 32768.0; if (newpeak > peak) peak = newpeak; t = iter.Next(); count++; } return true; }
bool MatrixSystem::LoadData(const QString& matrixFile, const QString& metadataFile) { // parse matrix file QFile file(matrixFile); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) { Log::Inst().Warning("Unable to open matrix file: " + matrixFile); return false; } QTextStream textStream(&file); QStringList sampleIds; bool bHeader = true; bool bPhylipFormat = true; Matrix matrix; while(!textStream.atEnd()) { QString dataRow = textStream.readLine(); if(dataRow.isEmpty()) break; QStringList dataItems; if(dataRow.count(' ') > dataRow.count('\t')) dataItems = dataRow.split(' ', QString::SkipEmptyParts); else dataItems = dataRow.split('\t', QString::SkipEmptyParts); if(bHeader) { bHeader = false; // check if this is a Phylip format distance matrix if(dataItems.size() == 1) { bool bNumber; int entries = dataItems.at(0).toInt(&bNumber); if(bNumber) { bPhylipFormat = true; continue; } } } sampleIds.push_back(dataItems.at(0)); QVector<double> row; for(int i = 1; i < dataItems.size(); ++i) row.push_back(dataItems.at(i).toDouble()); matrix.push_back(row); } // fill in upper triangular data since only the bottom triangular data may have been specified m_matrix.clear(); m_matrix.resize(matrix.size()); for(int r = 0; r < matrix.size(); ++r) { m_matrix[r].resize(matrix.size()); m_matrix[r][r] = 0; for(int c = 0; c < r; ++c) m_matrix[r][c] = m_matrix[c][r] = matrix[r][c]; } file.close(); // create samples for matrix file GetSamples()->SetSampleByName(sampleIds); // parse metadata file if(!GetSamples()->GetMetadata()->Load(metadataFile)) { Log::Inst().Error("Unable to parse metadata file."); return false; } return true; }
static void RasterizeTriangle(const ShadedGrid &sg, int u0, int v0, int u1, int v1, int u2, int v2, Bucket *bucket) { // Compute offsets in the vertex arrays for the three vertices of the // triangle to be rasterized int offset0 = sg.nu * v0 + u0; int offset1 = sg.nu * v1 + u1; int offset2 = sg.nu * v2 + u2; // Compute screen-space vertex positions of the triangle at start time; Point vx0[2], vx1[2], vx2[2]; vx0[0].set(sg.x0()[offset0], sg.y0()[offset0], sg.z0()[offset0], sg.w0()[offset0]); vx0[1].set(sg.x1()[offset0], sg.y1()[offset0], sg.z1()[offset0], sg.w1()[offset0]); vx1[0].set(sg.x0()[offset1], sg.y0()[offset1], sg.z0()[offset1], sg.w0()[offset1]); vx1[1].set(sg.x1()[offset1], sg.y1()[offset1], sg.z1()[offset1], sg.w1()[offset1]); vx2[0].set(sg.x0()[offset2], sg.y0()[offset2], sg.z0()[offset2], sg.w0()[offset2]); vx2[1].set(sg.x1()[offset2], sg.y1()[offset2], sg.z1()[offset2], sg.w1()[offset2]); // Now compute the bounding box of the triangle on the screen in // floating-point pixel coordinates. float xMin = vx0[0].x2d(), xMax = vx0[0].x2d(), yMin = vx0[0].y2d(), yMax = vx0[0].y2d(); for (int i = 0; i < 2; i++) { xMin = std::min(xMin, std::min(vx0[i].x2d(), std::min(vx1[i].x2d(), vx2[i].x2d()))); yMin = std::min(yMin, std::min(vx0[i].y2d(), std::min(vx1[i].y2d(), vx2[i].y2d()))); xMax = std::max(xMax, std::max(vx0[i].x2d(), std::max(vx1[i].x2d(), vx2[i].x2d()))); yMax = std::max(yMax, std::max(vx0[i].y2d(), std::max(vx1[i].y2d(), vx2[i].y2d()))); } // Compute integer pixel bounds, clamped to the bucket extent int ixMin = std::max((int)floorf(xMin), bucket->x0); int ixMax = std::min((int)ceilf(xMax), bucket->x1); int iyMin = std::max((int)floorf(yMin), bucket->y0); int iyMax = std::min((int)ceilf(yMax), bucket->y1); // Loop over the bounding box of the pixels that the triangle possibly // covers. for (int py = iyMin; py < iyMax; ++py) { for (int px = ixMin; px < ixMax; ++px) { // Get the set of samples for the pixel (px, py) float xSamples[MAX_SAMPLES_PER_PIXEL]; float ySamples[MAX_SAMPLES_PER_PIXEL]; float timeSamples[MAX_SAMPLES_PER_PIXEL]; GetSamples(px, py, bucket->kSamplesPerPixel, xSamples, ySamples, timeSamples); // Now loop over all of the samples for the pixel and see if // each one is inside the triangle. for (int sampleNum = 0; sampleNum < bucket->kSamplesPerPixel; ++sampleNum) { // Evaluate edge equations at sample position (sx,sy). float sx = xSamples[sampleNum], sy = ySamples[sampleNum]; float st = timeSamples[sampleNum]; // find the triangle at the time st // Triangle setup. // Compute the edge equation coefficients. float X0, X1, X2, Y0, Y1, Y2, Z0, Z1, Z2; Point vt0 = vx0[0] * (1 - st) + vx0[1] * st; Point vt1 = vx1[0] * (1 - st) + vx1[1] * st; Point vt2 = vx2[0] * (1 - st) + vx2[1] * st; X0 = vt0.x2d(); Y0 = vt0.y2d(); X1 = vt1.x2d(); Y1 = vt1.y2d(); X2 = vt2.x2d(); Y2 = vt2.y2d(); Z0 = vt0.z; Z1 = vt1.z; Z2 = vt2.z; float edge_a_0 = -(Y1 - Y0); float edge_a_1 = -(Y2 - Y1); float edge_a_2 = -(Y0 - Y2); float edge_b_0 = X1 - X0; float edge_b_1 = X2 - X1; float edge_b_2 = X0 - X2; float edge_c_0 = edge_a_0 * -X0 + edge_b_0 * -Y0; float edge_c_1 = edge_a_1 * -X1 + edge_b_1 * -Y1; float edge_c_2 = edge_a_2 * -X2 + edge_b_2 * -Y2; // Triangle area and inverse area float area = 0.5f * ((X1 - X0) * (Y2 - Y0) - (Y1 - Y0) * (X2 - X0)); float inv2Area = 1.f / (2.f * area); if (area <= .0) continue; float e0 = edge_a_0 * sx + edge_b_0 * sy + edge_c_0; float e1 = edge_a_1 * sx + edge_b_1 * sy + edge_c_1; float e2 = edge_a_2 * sx + edge_b_2 * sy + edge_c_2; if (e0 <= 0.f || e1 <= 0.f || e2 <= 0.f) // The sample is outside the triangle continue; // Compute interpolation weights float wt0 = e1 * inv2Area; float wt1 = e2 * inv2Area; float wt2 = e0 * inv2Area; // Interpolate z float z = (wt0 * Z0 + wt1 * Z1 + wt2 * Z2); // Z-test: is the z value closer than the z value currently // in the framebuffer? if (z < *bucket->Z(px, py, sampleNum)) { // z-test passed; update z in bucket framebuffer *bucket->Z(px, py, sampleNum) = z; // Interpolate R, G, B float r = (wt0 * sg.r()[offset0] + wt1 * sg.r()[offset1] + wt2 * sg.r()[offset2]); float g = (wt0 * sg.g()[offset0] + wt1 * sg.g()[offset1] + wt2 * sg.g()[offset2]); float b = (wt0 * sg.b()[offset0] + wt1 * sg.b()[offset1] + wt2 * sg.b()[offset2]); // Store r, g, b in framebuffer *bucket->R(px, py, sampleNum) = r; *bucket->G(px, py, sampleNum) = g; *bucket->B(px, py, sampleNum) = b; } } } } }
void Mixer::MixSameRate(int *channelFlags, WaveTrack * src, double t0, double t1) { if ((t0 - src->GetOffset()) >= src->GetNumSamples() / src->GetRate() || (t1 - src->GetOffset()) <= 0) return; int s0 = int ((t0 - src->GetOffset()) * src->GetRate() + 0.5); int s1 = int ((t1 - src->GetOffset()) * src->GetRate() + 0.5); int slen = s1 - s0; if (slen <= 0) return; if (slen > mBufferSize) slen = mBufferSize; GetSamples(src, s0, slen); double volume; if (mUseVolumeSlider) volume = mControlToolBar->GetSoundVol(); else volume = 1.0; Envelope *e = src->GetEnvelope(); e->GetValues(mEnvValues, slen, t0, 1.0 / mRate); // Mix it down to the appropriate tracks for (int c = 0; c < mNumChannels; c++) { if (!channelFlags[c]) continue; samplePtr destPtr; int skip; if (mInterleaved) { destPtr = mBuffer[0] + c*SAMPLE_SIZE(mFormat); skip = mNumChannels; } else { destPtr = mBuffer[c]; skip = 1; } // This is the mixing inner loop, which we want // as optimized as possible switch(mFormat) { case int16Sample: { short *dest = (short *)destPtr; short *temp = (short *)mTemp; for (int j = 0; j < slen; j++) { *dest += (short)rint(temp[j] * volume * mEnvValues[j]); dest += skip; } } break; case int24Sample: { int *dest = (int *)destPtr; int *temp = (int *)mTemp; for (int j = 0; j < slen; j++) { *dest += (int)rint(temp[j] * volume * mEnvValues[j]); dest += skip; } } break; case floatSample: { float *dest = (float *)destPtr; float *temp = (float *)mTemp; for (int j = 0; j < slen; j++) { *dest += temp[j] * volume * mEnvValues[j]; dest += skip; } } break; } // switch } }
void Mixer::MixDiffRates(int *channelFlags, WaveTrack * src, double t0, double t1) { if ((t0 - src->GetOffset()) >= src->GetNumSamples() / src->GetRate() || (t1 - src->GetOffset()) <= 0) return; int s0 = int ((t0 - src->GetOffset()) * src->GetRate()); // get a couple more samples than we need int slen = int ((t1 - t0) * src->GetRate()) + 2; int destlen = int ((t1 - t0) * mRate + 0.5); GetSamples(src, s0, slen); double volume; if (mUseVolumeSlider) volume = mControlToolBar->GetSoundVol(); else volume = 1.0; Envelope *e = src->GetEnvelope(); e->GetValues(mEnvValues, mBufferSize, t0, 1.0 / mRate); // Mix it down to the appropriate tracks for (int c = 0; c < mNumChannels; c++) { if (!channelFlags[c]) continue; samplePtr destPtr; int skip; if (mInterleaved) { destPtr = mBuffer[0] + c*SAMPLE_SIZE(mFormat); skip = mNumChannels; } else { destPtr = mBuffer[c]; skip = 1; } // This is the mixing inner loop, which we want // as optimized as possible int i = 0; switch(mFormat) { case int16Sample: { short *temp = (short *)mTemp; short *dest = (short *)destPtr; int frac = int(32768.0 * (t0 - s0/src->GetRate())); int fracstep = int(32768.0 * src->GetRate()/mRate + 0.5); for (int j = 0; j < destlen; j++) { short value = (temp[i]*(32768-frac) + temp[i+1]*frac) >> 15; frac += fracstep; i += (frac >> 15); // frac/32768 frac = (frac & 0x7FFF); // frac%32768 *dest += short(value * volume * mEnvValues[j] + 0.5); dest += skip; } } break; case int24Sample: { int *temp = (int *)mTemp; int *dest = (int *)destPtr; float frac = t0 - s0/src->GetRate(); float fracstep = src->GetRate()/mRate; for (int j = 0; j < destlen; j++) { float value = (temp[i]*(1.0-frac) + temp[i+1]*frac); frac += fracstep; int integerPart = (int)frac; i += integerPart; frac -= (float)integerPart; *dest += int(value * volume * mEnvValues[j] + 0.5); dest += skip; } } break; case floatSample: { float *temp = (float *)mTemp; float *dest = (float *)destPtr; float frac = t0 - s0/src->GetRate(); float fracstep = src->GetRate()/mRate; for (int j = 0; j < destlen; j++) { float value = temp[i]*(1.0-frac) + temp[i+1]*frac; frac += fracstep; int integerPart = (int)frac; i += integerPart; frac -= (float)integerPart; *dest += value * volume * mEnvValues[j]; dest += skip; } } break; } // switch } }
bool VampEffect::Process() { if (!mPlugin) return false; TrackListIterator iter(mWaveTracks); int count = 0; WaveTrack *left = (WaveTrack *)iter.First(); bool multiple = false; int prevTrackChannels = 0; TrackListIterator scooter(iter); if (left->GetLinked()) scooter.Next(); if (scooter.Next()) { // if there is another track beyond this one and any linked one, // then we're processing more than one track. That means we // should use the originating track name in each new label // track's name, to make clear which is which multiple = true; } while (left) { sampleCount lstart, rstart; sampleCount len; GetSamples(left, &lstart, &len); WaveTrack *right = NULL; int channels = 1; if (left->GetLinked()) { right = (WaveTrack *)iter.Next(); channels = 2; GetSamples(right, &rstart, &len); } size_t step = mPlugin->getPreferredStepSize(); size_t block = mPlugin->getPreferredBlockSize(); bool initialiseRequired = true; if (block == 0) { if (step != 0) block = step; else block = 1024; } if (step == 0) { step = block; } if (prevTrackChannels > 0) { // Plugin has already been initialised, so if the number of // channels remains the same, we only need to do a reset. // Otherwise we need to re-construct the whole plugin, // because a Vamp plugin can't be re-initialised. if (prevTrackChannels == channels) { mPlugin->reset(); initialiseRequired = false; } else { //!!! todo: retain parameters previously set Init(); } } if (initialiseRequired) { if (!mPlugin->initialise(channels, step, block)) { wxMessageBox(_("Sorry, Vamp Plug-in failed to initialize.")); return false; } } LabelTrack *ltrack = mFactory->NewLabelTrack(); if (!multiple) { ltrack->SetName(GetEffectName()); } else { ltrack->SetName(wxString::Format(wxT("%s: %s"), left->GetName().c_str(), GetEffectName().c_str())); } mTracks->Add(ltrack); float **data = new float*[channels]; for (int c = 0; c < channels; ++c) data[c] = new float[block]; sampleCount originalLen = len; sampleCount ls = lstart; sampleCount rs = rstart; while (len) { int request = block; if (request > len) request = len; if (left) left->Get((samplePtr)data[0], floatSample, ls, request); if (right) right->Get((samplePtr)data[1], floatSample, rs, request); if (request < (int)block) { for (int c = 0; c < channels; ++c) { for (int i = request; i < (int)block; ++i) { data[c][i] = 0.f; } } } Vamp::RealTime timestamp = Vamp::RealTime::frame2RealTime (ls, (int)(mRate + 0.5)); Vamp::Plugin::FeatureSet features = mPlugin->process(data, timestamp); AddFeatures(ltrack, features); if (len > (int)step) len -= step; else len = 0; ls += step; rs += step; if (channels > 1) { if (TrackGroupProgress(count, (ls - lstart) / double(originalLen))) return false; } else { if (TrackProgress(count, (ls - lstart) / double(originalLen))) return false; } } Vamp::Plugin::FeatureSet features = mPlugin->getRemainingFeatures(); AddFeatures(ltrack, features); prevTrackChannels = channels; left = (WaveTrack *)iter.Next(); } return true; }
void TranscriptionToolBar::OnAutomateSelection(wxCommandEvent & WXUNUSED(event)) { //If IO is busy, abort immediately if (gAudioIO->IsBusy()) { SetButton(false,mButtons[TTB_EndOff]); return; } wxBusyCursor busy; mVk->AdjustThreshold(GetSensitivity()); AudacityProject *p = GetActiveProject(); TrackList *tl = p->GetTracks(); TrackListIterator iter(tl); Track *t = iter.First(); //Make a track if(t) { sampleCount start,len; GetSamples((WaveTrack*)t, &start,&len); //Adjust length to end if selection is null if(len == 0) { len = start; start = 0; } int lastlen = 0; sampleCount newStart, newEnd; double newStartPos, newEndPos; //This is the minumum word size in samples (.05 is 50 ms) int minWordSize = (int)(((WaveTrack*)t)->GetRate() * .05); //Continue until we have processed the entire //region, or we are making no progress. while(len > 0 && lastlen != len) { lastlen = len; newStart = mVk->OnForward(*(WaveTrack*)t,start,len); //JKC: If no start found then don't add any labels. if( newStart==start) break; //Adjust len by the NEW start position len -= (newStart - start); //Adjust len by the minimum word size len -= minWordSize; //OK, now we have found a NEW starting point. A 'word' should be at least //50 ms long, so jump ahead minWordSize newEnd = mVk->OffForward(*(WaveTrack*)t,newStart+minWordSize, len); //If newEnd didn't move, we should give up, because // there isn't another end before the end of the selection. if(newEnd == (newStart + minWordSize)) break; //Adjust len by the NEW word end len -= (newEnd - newStart); //Calculate the start and end of the words, in seconds newStartPos = newStart / ((WaveTrack*)t)->GetRate(); newEndPos = newEnd / ((WaveTrack*)t)->GetRate(); //Increment start = newEnd; p->DoAddLabel(SelectedRegion(newStartPos, newEndPos)); p->RedrawProject(); } SetButton(false, mButtons[TTB_AutomateSelection]); } }
bool VampEffect::Process() { if (!mPlugin) { return false; } int count = 0; bool multiple = false; unsigned prevTrackChannels = 0; if (GetNumWaveGroups() > 1) { // if there is another track beyond this one and any linked one, // then we're processing more than one track. That means we // should use the originating track name in each NEW label // track's name, to make clear which is which multiple = true; } std::vector<std::shared_ptr<Effect::AddedAnalysisTrack>> addedTracks; for (auto leader : inputTracks()->Leaders<const WaveTrack>()) { auto channelGroup = TrackList::Channels(leader); auto left = *channelGroup.first++; sampleCount lstart, rstart = 0; sampleCount len; GetSamples(left, &lstart, &len); unsigned channels = 1; // channelGroup now contains all but the first channel const WaveTrack *right = channelGroup.size() ? *channelGroup.first++ : nullptr; if (right) { channels = 2; GetSamples(right, &rstart, &len); } // TODO: more-than-two-channels size_t step = mPlugin->getPreferredStepSize(); size_t block = mPlugin->getPreferredBlockSize(); bool initialiseRequired = true; if (block == 0) { if (step != 0) { block = step; } else { block = 1024; } } if (step == 0) { step = block; } if (prevTrackChannels > 0) { // Plugin has already been initialised, so if the number of // channels remains the same, we only need to do a reset. // Otherwise we need to re-construct the whole plugin, // because a Vamp plugin can't be re-initialised. if (prevTrackChannels == channels) { mPlugin->reset(); initialiseRequired = false; } else { //!!! todo: retain parameters previously set Init(); } } if (initialiseRequired) { if (!mPlugin->initialise(channels, step, block)) { Effect::MessageBox(_("Sorry, Vamp Plug-in failed to initialize.")); return false; } } const auto effectName = GetSymbol().Translation(); addedTracks.push_back(AddAnalysisTrack( multiple ? wxString::Format( _("%s: %s"), left->GetName(), effectName ) : effectName )); LabelTrack *ltrack = addedTracks.back()->get(); FloatBuffers data{ channels, block }; auto originalLen = len; auto ls = lstart; auto rs = rstart; while (len != 0) { const auto request = limitSampleBufferSize( block, len ); if (left) { left->Get((samplePtr)data[0].get(), floatSample, ls, request); } if (right) { right->Get((samplePtr)data[1].get(), floatSample, rs, request); } if (request < block) { for (unsigned int c = 0; c < channels; ++c) { for (decltype(block) i = request; i < block; ++i) { data[c][i] = 0.f; } } } // UNSAFE_SAMPLE_COUNT_TRUNCATION // Truncation in case of very long tracks! Vamp::RealTime timestamp = Vamp::RealTime::frame2RealTime( long( ls.as_long_long() ), (int)(mRate + 0.5) ); Vamp::Plugin::FeatureSet features = mPlugin->process( reinterpret_cast< float** >( data.get() ), timestamp); AddFeatures(ltrack, features); if (len > (int)step) { len -= step; } else { len = 0; } ls += step; rs += step; if (channels > 1) { if (TrackGroupProgress(count, (ls - lstart).as_double() / originalLen.as_double() )) { return false; } } else { if (TrackProgress(count, (ls - lstart).as_double() / originalLen.as_double() )) { return false; } } } Vamp::Plugin::FeatureSet features = mPlugin->getRemainingFeatures(); AddFeatures(ltrack, features); prevTrackChannels = channels; } // All completed without cancellation, so commit the addition of tracks now for (auto &addedTrack : addedTracks) addedTrack->Commit(); return true; }
bool VSTEffect::Process() { CopyInputTracks(); bool bGoodResult = true; mInBuffer = NULL; mOutBuffer = NULL; TrackListIterator iter(mOutputTracks); int count = 0; bool clear = false; WaveTrack *left = (WaveTrack *) iter.First(); while (left) { WaveTrack *right; sampleCount len; sampleCount lstart; sampleCount rstart; GetSamples(left, &lstart, &len); mChannels = 1; right = NULL; rstart = 0; if (left->GetLinked() && mInputs > 1) { right = (WaveTrack *) iter.Next(); GetSamples(right, &rstart, &len); clear = false; mChannels = 2; } if (mBlockSize == 0) { mBlockSize = left->GetMaxBlockSize() * 2; // Some VST effects (Antress Modern is an example), do not like // overly large block sizes. Unfortunately, I have not found a // way to determine if the effect has a maximum it will support, // so just limit to small value for now. This will increase // processing time and, it's a shame, because most plugins seem // to be able to handle much larger sizes. if (mBlockSize > 8192) { // The Antress limit mBlockSize = 8192; } mInBuffer = new float *[mInputs]; for (int i = 0; i < mInputs; i++) { mInBuffer[i] = new float[mBlockSize]; } mOutBuffer = new float *[mOutputs]; for (int i = 0; i < mOutputs; i++) { mOutBuffer[i] = new float[mBlockSize]; } // Turn the power off callDispatcher(effMainsChanged, 0, 0, NULL, 0.0); // Set processing parameters callDispatcher(effSetSampleRate, 0, 0, NULL, left->GetRate()); callDispatcher(effSetBlockSize, 0, mBlockSize, NULL, 0.0); } // Clear unused input buffers if (!right && !clear) { for (int i = 1; i < mInputs; i++) { for (int j = 0; j < mBlockSize; j++) { mInBuffer[i][j] = 0.0; } } clear = true; } bGoodResult = ProcessStereo(count, left, right, lstart, rstart, len); if (!bGoodResult) { break; } left = (WaveTrack *) iter.Next(); count++; } if (mOutBuffer) { for (int i = 0; i < mOutputs; i++) { delete mOutBuffer[i]; } delete [] mOutBuffer; mOutBuffer = NULL; } if (mInBuffer) { for (int i = 0; i < mInputs; i++) { delete mInBuffer[i]; } delete [] mInBuffer; mInBuffer = NULL; } ReplaceProcessedTracks(bGoodResult); return bGoodResult; }