1178
1181
// Offset all recorded tracks to account for latency
1180
double latencyCorrection = 0;
1181
gPrefs->Read(wxT("/AudioIO/LatencyCorrection"), &latencyCorrection);
1183
1183
if( mCaptureTracks.GetCount() > 0 )
1186
// We only apply latency correction when we actually played back
1187
// tracks during the recording. If we did not play back tracks,
1188
// there's nothing we could be out of sync with. This also covers the
1189
// case that we do not apply latency correction when recording the
1190
// first track in a project.
1192
double latencyCorrection = 0;
1193
gPrefs->Read(wxT("/AudioIO/LatencyCorrection"), &latencyCorrection);
1195
double recordingOffset =
1196
mLastRecordingOffset + latencyCorrection / 1000.0;
1185
1198
for( unsigned int i = 0; i < mCaptureTracks.GetCount(); i++ )
1187
1200
delete mCaptureBuffers[i];
1188
mCaptureTracks[i]->Flush();
1189
mCaptureTracks[i]->Offset(mLastRecordingOffset +
1190
latencyCorrection/1000.0);
1202
WaveTrack* track = mCaptureTracks[i];
1205
if (mPlaybackTracks.GetCount() > 0)
1206
{ // only do latency correction if some tracks are being played back
1207
WaveTrackArray playbackTracks;
1208
AudacityProject *p = GetActiveProject();
1209
// we need to get this as mPlaybackTracks does not contain tracks being recorded into
1210
playbackTracks = p->GetTracks()->GetWaveTrackArray(false);
1211
bool appendRecord = false;
1212
for( unsigned int j = 0; j < playbackTracks.GetCount(); j++)
1213
{ // find if we are recording into an existing track (append-record)
1214
WaveTrack* trackP = playbackTracks[j];
1215
if( track == trackP )
1217
if( track->GetStartTime() != mT0 ) // in a new track if these are equal
1219
appendRecord = true;
1225
{ // append-recording
1226
if (recordingOffset < 0)
1227
track->Clear(mT0, mT0 - recordingOffset); // cut the latency out
1229
track->InsertSilence(mT0, recordingOffset); // put silence in
1232
{ // recording into a new track
1233
track->SetOffset(track->GetStartTime() + recordingOffset);
1234
if(track->GetEndTime() < 0.)
1236
wxMessageDialog m(NULL, _("Latency setting has caused the recorded audio to be hidden before zero.\nAudacity has brought it back to start at zero.\nYou may have to use the Time Shift Tool (<---> or F5) to drag the track to the right place."), _("Latency problem"), wxOK);
1238
track->SetOffset(0.);
1193
1244
delete[] mCaptureBuffers;
1646
1688
return commonlyAvail;
1691
wxString AudioIO::GetDeviceInfo()
1693
wxStringOutputStream o;
1694
wxTextOutputStream s(o, wxEOL_UNIX);
1695
wxString e(wxT("\n"));
1697
if (IsStreamActive()) {
1698
return wxT("Stream is active ... unable to gather information.");
1701
#if defined(USE_PORTMIXER)
1702
const PaDeviceInfo* info;
1704
#if USE_PORTAUDIO_V19
1705
int recDeviceNum = Pa_GetDefaultInputDevice();
1706
int playDeviceNum = Pa_GetDefaultOutputDevice();
1708
int recDeviceNum = Pa_GetDefaultInputDeviceID();
1709
int playDeviceNum = Pa_GetDefaultOutputDeviceID();
1712
s << wxT("==============================") << e;
1713
s << wxT("Default capture device number: ") << recDeviceNum << e;
1714
s << wxT("Default playback device number: ") << playDeviceNum << e;
1716
// Sometimes PortAudio returns -1 if it cannot find a suitable default
1717
// device, so we just use the first one available
1718
if (recDeviceNum < 0)
1720
if (playDeviceNum < 0)
1723
wxString recDevice = gPrefs->Read(wxT("/AudioIO/RecordingDevice"), wxT(""));
1724
wxString playDevice = gPrefs->Read(wxT("/AudioIO/PlaybackDevice"), wxT(""));
1727
// msmeyer: This tries to open the device with the highest samplerate
1728
// available on this device, using 44.1kHz as the default, if the info
1729
// cannot be fetched.
1731
#if USE_PORTAUDIO_V19
1732
int cnt = Pa_GetDeviceCount();
1734
int cnt = Pa_CountDevices();
1738
s << wxT("No devices found\n");
1739
return o.GetString();
1742
for (j = 0; j < cnt; j++) {
1743
s << wxT("==============================") << e;
1745
info = Pa_GetDeviceInfo(j);
1747
s << wxT("Device info unavailable for: ") << j << wxT("\n");
1751
wxString name = DeviceName(info);
1753
s << wxT("Device ID: ") << j << e;
1754
s << wxT("Device name: ") << name << e;
1755
s << wxT("Input channels: ") << info->maxInputChannels << e;
1756
s << wxT("Output channels: ") << info->maxOutputChannels << e;
1757
s << wxT("Low Input Latency: ") << info->defaultLowInputLatency << e;
1758
s << wxT("Low Output Latency: ") << info->defaultLowOutputLatency << e;
1759
s << wxT("High Input Latency: ") << info->defaultHighInputLatency << e;
1760
s << wxT("High Output Latency: ") << info->defaultHighOutputLatency << e;
1762
wxArrayLong rates = GetSupportedPlaybackRates(name, 0.0);
1764
s << wxT("Supported Rates:") << e;
1765
for (int k = 0; k < (int) rates.GetCount(); k++) {
1766
s << wxT(" ") << (int)rates[k] << e;
1769
if (name == playDevice && info->maxOutputChannels > 0)
1772
if (name == recDevice && info->maxInputChannels > 0)
1776
s << wxT("==============================") << e;
1777
s << wxT("Selected capture device: ") << recDeviceNum << wxT(" - ") << recDevice << e;
1778
s << wxT("Selected playback device: ") << playDeviceNum << wxT(" - ") << playDevice << e;
1780
wxArrayLong supportedSampleRates = GetSupportedSampleRates(playDevice, recDevice);
1782
s << wxT("Supported Rates:");
1783
for (int k = 0; k < (int) supportedSampleRates.GetCount(); k++) {
1784
s << wxT(" ") << (int)supportedSampleRates[k] << e;
1787
int highestSampleRate = supportedSampleRates[supportedSampleRates.GetCount() - 1];
1788
bool EmulateMixerInputVol = true;
1789
bool EmulateMixerOutputVol = true;
1790
float MixerInputVol = 1.0;
1791
float MixerOutputVol = 1.0;
1795
#if USE_PORTAUDIO_V19
1799
PaStreamParameters playbackParameters;
1801
playbackParameters.device = playDeviceNum;
1802
playbackParameters.sampleFormat = paFloat32;
1803
playbackParameters.hostApiSpecificStreamInfo = NULL;
1804
playbackParameters.channelCount = 2;
1805
if (Pa_GetDeviceInfo(playDeviceNum))
1806
playbackParameters.suggestedLatency =
1807
Pa_GetDeviceInfo(playDeviceNum)->defaultLowOutputLatency;
1809
playbackParameters.suggestedLatency = 100; // we're just probing anyway
1811
PaStreamParameters captureParameters;
1813
captureParameters.device = recDeviceNum;
1814
captureParameters.sampleFormat = paFloat32;;
1815
captureParameters.hostApiSpecificStreamInfo = NULL;
1816
captureParameters.channelCount = 2;
1817
if (Pa_GetDeviceInfo(recDeviceNum))
1818
captureParameters.suggestedLatency =
1819
Pa_GetDeviceInfo(recDeviceNum)->defaultLowInputLatency;
1821
captureParameters.suggestedLatency = 100; // we're just probing anyway
1823
error = Pa_OpenStream(&stream,
1824
&captureParameters, &playbackParameters,
1825
highestSampleRate, paFramesPerBufferUnspecified,
1826
paClipOff | paDitherOff,
1827
audacityAudioCallback, NULL);
1830
error = Pa_OpenStream(&stream,
1831
&captureParameters, NULL,
1832
highestSampleRate, paFramesPerBufferUnspecified,
1833
paClipOff | paDitherOff,
1834
audacityAudioCallback, NULL);
1839
PortAudioStream *stream;
1841
error = Pa_OpenStream(&stream, recDeviceNum, 2, paFloat32, NULL,
1842
playDeviceNum, 2, paFloat32, NULL,
1843
highestSampleRate, 512, 1, paClipOff | paDitherOff,
1844
audacityAudioCallback, NULL);
1847
error = Pa_OpenStream(&stream, recDeviceNum, 2, paFloat32, NULL,
1848
paNoDevice, 0, paFloat32, NULL,
1849
highestSampleRate, 512, 1, paClipOff | paDitherOff,
1850
audacityAudioCallback, NULL);
1856
s << wxT("Recieved ") << error << wxT(" while opening devices") << e;
1857
return o.GetString();
1860
PxMixer *PortMixer = Px_OpenMixer(stream, 0);
1863
s << wxT("Unable to open Portmixer") << e;
1864
Pa_CloseStream(stream);
1865
return o.GetString();
1868
s << wxT("==============================") << e;
1869
s << wxT("Available mixers:") << e;
1871
cnt = Px_GetNumMixers(stream);
1872
for (int i = 0; i < cnt; i++) {
1873
wxString name(Px_GetMixerName(stream, i), wxConvLocal);
1874
s << i << wxT(" - ") << name << e;
1877
s << wxT("==============================") << e;
1878
s << wxT("Available capture sources:") << e;
1879
cnt = Px_GetNumInputSources(PortMixer);
1880
for (int i = 0; i < cnt; i++) {
1881
wxString name(Px_GetInputSourceName(PortMixer, i), wxConvLocal);
1882
s << i << wxT(" - ") << name << e;
1885
s << wxT("==============================") << e;
1886
s << wxT("Available playback volumes:") << e;
1887
cnt = Px_GetNumOutputVolumes(PortMixer);
1888
for (int i = 0; i < cnt; i++) {
1889
wxString name(Px_GetOutputVolumeName(PortMixer, i), wxConvLocal);
1890
s << i << wxT(" - ") << name << e;
1893
// Determine mixer capabilities - it it doesn't support either
1894
// input or output, we emulate them (by multiplying this value
1895
// by all incoming/outgoing samples)
1897
MixerOutputVol = Px_GetPCMOutputVolume(PortMixer);
1898
EmulateMixerOutputVol = false;
1899
Px_SetPCMOutputVolume(PortMixer, 0.0);
1900
if (Px_GetPCMOutputVolume(PortMixer) > 0.1)
1901
EmulateMixerOutputVol = true;
1902
Px_SetPCMOutputVolume(PortMixer, 0.2f);
1903
if (Px_GetPCMOutputVolume(PortMixer) < 0.1 ||
1904
Px_GetPCMOutputVolume(PortMixer) > 0.3)
1905
EmulateMixerOutputVol = true;
1906
Px_SetPCMOutputVolume(PortMixer, MixerOutputVol);
1908
MixerInputVol = Px_GetInputVolume(PortMixer);
1909
EmulateMixerInputVol = false;
1910
Px_SetInputVolume(PortMixer, 0.0);
1911
if (Px_GetInputVolume(PortMixer) > 0.1)
1912
EmulateMixerInputVol = true;
1913
Px_SetInputVolume(PortMixer, 0.2f);
1914
if (Px_GetInputVolume(PortMixer) < 0.1 ||
1915
Px_GetInputVolume(PortMixer) > 0.3)
1916
EmulateMixerInputVol = true;
1917
Px_SetInputVolume(PortMixer, MixerInputVol);
1919
Pa_CloseStream(stream);
1921
s << wxT("==============================") << e;
1922
s << wxT("Capture volume is ") << (EmulateMixerInputVol? wxT("emulated"): wxT("native")) << e;
1923
s << wxT("Capture volume is ") << (EmulateMixerOutputVol? wxT("emulated"): wxT("native")) << e;
1925
Px_CloseMixer(PortMixer);
1929
return o.GetString();
1649
1932
// This method is the data gateway between the audio thread (which
1650
1933
// communicates with the disk) and the PortAudio callback thread
1651
1934
// (which communicates with the audio device.
1852
2135
unsigned int i;
2138
// Send data to VU meters
2140
// It's critical that we don't update the meters while
2141
// StopStream is trying to stop PortAudio, otherwise it can
2142
// lead to a freeze. We use two variables to synchronize:
2143
// mUpdatingMeters tells StopStream when the callback is about
2144
// to enter the code where it might update the meters, and
2145
// mUpdateMeters is how the rest of the code tells the callback
2146
// when it is allowed to actually do the updating. Note that
2147
// mUpdatingMeters must be set first to avoid a race condition.
2148
gAudioIO->mUpdatingMeters = true;
2149
if (gAudioIO->mUpdateMeters) {
2151
if (gAudioIO->mOutputMeter &&
2152
!gAudioIO->mOutputMeter->IsMeterDisabled() &&
2154
gAudioIO->mOutputMeter->UpdateDisplay(numPlaybackChannels,
2156
(float *)outputBuffer);
2159
if (gAudioIO->mInputMeter &&
2160
!gAudioIO->mInputMeter->IsMeterDisabled() &&
2162
if (gAudioIO->mCaptureFormat == floatSample)
2163
gAudioIO->mInputMeter->UpdateDisplay(numCaptureChannels,
2165
(float *)inputBuffer);
2167
CopySamples((samplePtr)inputBuffer, gAudioIO->mCaptureFormat,
2168
(samplePtr)tempFloats, floatSample,
2169
framesPerBuffer * numCaptureChannels);
2170
gAudioIO->mInputMeter->UpdateDisplay(numCaptureChannels,
2176
gAudioIO->mUpdatingMeters = false;
2178
#ifdef EXPERIMENTAL_SMART_RECORD
2179
// Stop recording if 'silence' is detected
2180
if(gAudioIO->mPauseRec && inputBuffer) {
2181
if(gAudioIO->mInputMeter->GetMaxPeak() < gAudioIO->mSilenceLevel ) {
2182
if(!gAudioIO->IsPaused()) {
2183
AudacityProject *p = GetActiveProject();
2184
wxCommandEvent dummyEvt;
2185
p->GetControlToolBar()->OnPause(dummyEvt);
2189
if(gAudioIO->IsPaused()) {
2190
AudacityProject *p = GetActiveProject();
2191
wxCommandEvent dummyEvt;
2192
p->GetControlToolBar()->OnPause(dummyEvt);
1855
2197
if( gAudioIO->mPaused )
1857
2199
if (outputBuffer && numPlaybackChannels > 0)