mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-09 00:04:56 +01:00
Synced string array in sfdb_ui.cc with ImportMode enum.
Cleaned up CoreAudioSource by using CAAudioFile. git-svn-id: svn://localhost/ardour2/trunk@881 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
9bc22f6f86
commit
78e13c37f4
10 changed files with 2436 additions and 106 deletions
|
|
@ -54,7 +54,8 @@ DISPLAYCONTROL(ShowMeasures)
|
|||
DISPLAYCONTROL(ShowWaveforms)
|
||||
DISPLAYCONTROL(ShowWaveformsRecording)
|
||||
|
||||
IMPORTMODE(ImportAsRegion)
|
||||
IMPORTMODE(ImportAsTrack)
|
||||
IMPORTMODE(ImportAsTapeTrack)
|
||||
IMPORTMODE(ImportToTrack)
|
||||
// if this is changed, remember to update the string table in sfdb_ui.cc
|
||||
IMPORTMODE(ImportAsRegion=0)
|
||||
IMPORTMODE(ImportToTrack=1)
|
||||
IMPORTMODE(ImportAsTrack=2)
|
||||
IMPORTMODE(ImportAsTapeTrack=3)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include <ardour/source_factory.h>
|
||||
|
||||
#include "ardour_ui.h"
|
||||
#include "editing.h"
|
||||
#include "gui_thread.h"
|
||||
#include "prompter.h"
|
||||
#include "sfdb_ui.h"
|
||||
|
|
@ -305,6 +306,15 @@ SoundFileBox::field_selected ()
|
|||
}
|
||||
}
|
||||
|
||||
// this needs to be kept in sync with the ImportMode enum defined in editing.h and editing_syms.h.
|
||||
static const char *import_mode_strings[] = {
|
||||
X_("Add to Region list"),
|
||||
X_("Add to selected Track(s)"),
|
||||
X_("Add as new Track(s)"),
|
||||
X_("Add as new Tape Track(s)"),
|
||||
0
|
||||
};
|
||||
|
||||
SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s)
|
||||
: ArdourDialog (title, false),
|
||||
chooser (Gtk::FILE_CHOOSER_ACTION_OPEN)
|
||||
|
|
@ -339,13 +349,6 @@ SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
|
|||
show_all ();
|
||||
}
|
||||
|
||||
static const char *import_mode_strings[] = {
|
||||
X_("Add to Region list"),
|
||||
X_("Add as new Track(s)"),
|
||||
X_("Add to selected Track(s)"),
|
||||
0
|
||||
};
|
||||
|
||||
vector<string> SoundFileOmega::mode_strings;
|
||||
|
||||
SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s)
|
||||
|
|
|
|||
1241
libs/appleutility/CAAudioFile.cpp
Normal file
1241
libs/appleutility/CAAudioFile.cpp
Normal file
File diff suppressed because it is too large
Load diff
439
libs/appleutility/CAAudioFile.h
Normal file
439
libs/appleutility/CAAudioFile.h
Normal file
|
|
@ -0,0 +1,439 @@
|
|||
/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
|
||||
copyrights in this original Apple software (the "Apple Software"), to use,
|
||||
reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions of
|
||||
the Apple Software. Neither the name, trademarks, service marks or logos of
|
||||
Apple Computer, Inc. may be used to endorse or promote products derived from the
|
||||
Apple Software without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or implied,
|
||||
are granted by Apple herein, including but not limited to any patent rights that
|
||||
may be infringed by your derivative works or by other works in which the Apple
|
||||
Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
|
||||
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
|
||||
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*=============================================================================
|
||||
CAAudioFile.h
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef __CAAudioFile_h__
|
||||
#define __CAAudioFile_h__
|
||||
|
||||
#include <AvailabilityMacros.h>
|
||||
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#else
|
||||
#include <AudioToolbox.h>
|
||||
#endif
|
||||
|
||||
#include "CAStreamBasicDescription.h"
|
||||
#include "CABufferList.h"
|
||||
#include "CAAudioChannelLayout.h"
|
||||
#include "CAXException.h"
|
||||
#include "CAMath.h"
|
||||
|
||||
#ifndef CAAF_USE_EXTAUDIOFILE
|
||||
// option: use AudioToolbox/ExtAudioFile.h? Only available on Tiger.
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3
|
||||
// we are building software that must be deployable on Panther or earlier
|
||||
#define CAAF_USE_EXTAUDIOFILE 0
|
||||
#else
|
||||
// else we require Tiger and can use the API
|
||||
#define CAAF_USE_EXTAUDIOFILE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_4
|
||||
// we have pre-Tiger headers; add our own declarations
|
||||
typedef UInt32 AudioFileTypeID;
|
||||
enum {
|
||||
kExtAudioFileError_InvalidProperty = -66561,
|
||||
kExtAudioFileError_InvalidPropertySize = -66562,
|
||||
kExtAudioFileError_NonPCMClientFormat = -66563,
|
||||
kExtAudioFileError_InvalidChannelMap = -66564, // number of channels doesn't match format
|
||||
kExtAudioFileError_InvalidOperationOrder = -66565,
|
||||
kExtAudioFileError_InvalidDataFormat = -66566,
|
||||
kExtAudioFileError_MaxPacketSizeUnknown = -66567,
|
||||
kExtAudioFileError_InvalidSeek = -66568, // writing, or offset out of bounds
|
||||
kExtAudioFileError_AsyncWriteTooLarge = -66569,
|
||||
kExtAudioFileError_AsyncWriteBufferOverflow = -66570 // an async write could not be completed in time
|
||||
};
|
||||
#else
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <AudioToolbox/ExtendedAudioFile.h>
|
||||
#else
|
||||
#include "ExtendedAudioFile.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// _______________________________________________________________________________________
|
||||
// Wrapper class for an AudioFile, supporting encode/decode to/from a PCM client format
|
||||
class CAAudioFile {
|
||||
public:
|
||||
// implementation-independent helpers
|
||||
void Open(const char *filePath) {
|
||||
FSRef fsref;
|
||||
XThrowIfError(FSPathMakeRef((UInt8 *)filePath, &fsref, NULL), "locate audio file");
|
||||
Open(fsref);
|
||||
}
|
||||
|
||||
bool HasConverter() const { return GetConverter() != NULL; }
|
||||
|
||||
double GetDurationSeconds() {
|
||||
double sr = GetFileDataFormat().mSampleRate;
|
||||
return fnonzero(sr) ? GetNumberFrames() / sr : 0.;
|
||||
}
|
||||
// will be 0 if the file's frames/packet is 0 (variable)
|
||||
// or the file's sample rate is 0 (unknown)
|
||||
|
||||
#if CAAF_USE_EXTAUDIOFILE
|
||||
public:
|
||||
CAAudioFile() : mExtAF(NULL) { }
|
||||
virtual ~CAAudioFile() { if (mExtAF) Close(); }
|
||||
|
||||
void Open(const FSRef &fsref) {
|
||||
// open an existing file
|
||||
XThrowIfError(ExtAudioFileOpen(&fsref, &mExtAF), "ExtAudioFileOpen failed");
|
||||
}
|
||||
|
||||
void CreateNew(const FSRef &inParentDir, CFStringRef inFileName, AudioFileTypeID inFileType, const AudioStreamBasicDescription &inStreamDesc, const AudioChannelLayout *inChannelLayout=NULL) {
|
||||
XThrowIfError(ExtAudioFileCreateNew(&inParentDir, inFileName, inFileType, &inStreamDesc, inChannelLayout, &mExtAF), "ExtAudioFileCreateNew failed");
|
||||
}
|
||||
|
||||
void Wrap(AudioFileID fileID, bool forWriting) {
|
||||
// use this to wrap an AudioFileID opened externally
|
||||
XThrowIfError(ExtAudioFileWrapAudioFileID(fileID, forWriting, &mExtAF), "ExtAudioFileWrapAudioFileID failed");
|
||||
}
|
||||
|
||||
void Close() {
|
||||
XThrowIfError(ExtAudioFileDispose(mExtAF), "ExtAudioFileClose failed");
|
||||
mExtAF = NULL;
|
||||
}
|
||||
|
||||
const CAStreamBasicDescription &GetFileDataFormat() {
|
||||
UInt32 size = sizeof(mFileDataFormat);
|
||||
XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_FileDataFormat, &size, &mFileDataFormat), "Couldn't get file's data format");
|
||||
return mFileDataFormat;
|
||||
}
|
||||
|
||||
const CAAudioChannelLayout & GetFileChannelLayout() {
|
||||
return FetchChannelLayout(mFileChannelLayout, kExtAudioFileProperty_FileChannelLayout);
|
||||
}
|
||||
|
||||
void SetFileChannelLayout(const CAAudioChannelLayout &layout) {
|
||||
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_FileChannelLayout, layout.Size(), &layout.Layout()), "Couldn't set file's channel layout");
|
||||
mFileChannelLayout = layout;
|
||||
}
|
||||
|
||||
const CAStreamBasicDescription &GetClientDataFormat() {
|
||||
UInt32 size = sizeof(mClientDataFormat);
|
||||
XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_ClientDataFormat, &size, &mClientDataFormat), "Couldn't get client data format");
|
||||
return mClientDataFormat;
|
||||
}
|
||||
|
||||
const CAAudioChannelLayout & GetClientChannelLayout() {
|
||||
return FetchChannelLayout(mClientChannelLayout, kExtAudioFileProperty_ClientChannelLayout);
|
||||
}
|
||||
|
||||
void SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout=NULL) {
|
||||
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_ClientDataFormat, sizeof(dataFormat), &dataFormat), "Couldn't set client format");
|
||||
if (layout)
|
||||
SetClientChannelLayout(*layout);
|
||||
}
|
||||
|
||||
void SetClientChannelLayout(const CAAudioChannelLayout &layout) {
|
||||
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_ClientChannelLayout, layout.Size(), &layout.Layout()), "Couldn't set client channel layout");
|
||||
}
|
||||
|
||||
AudioConverterRef GetConverter() const {
|
||||
UInt32 size = sizeof(AudioConverterRef);
|
||||
AudioConverterRef converter;
|
||||
XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_AudioConverter, &size, &converter), "Couldn't get file's AudioConverter");
|
||||
return converter;
|
||||
}
|
||||
|
||||
OSStatus SetConverterProperty(AudioConverterPropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData, bool inCanFail=false)
|
||||
{
|
||||
OSStatus err = AudioConverterSetProperty(GetConverter(), inPropertyID, inPropertyDataSize, inPropertyData);
|
||||
if (!inCanFail)
|
||||
XThrowIfError(err, "Couldn't set audio converter property");
|
||||
if (!err) {
|
||||
// must tell the file that we have changed the converter; a NULL converter config is sufficient
|
||||
CFPropertyListRef config = NULL;
|
||||
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_ConverterConfig, sizeof(CFPropertyListRef), &config), "couldn't signal the file that the converter has changed");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
SInt64 GetNumberFrames() {
|
||||
SInt64 length;
|
||||
UInt32 size = sizeof(SInt64);
|
||||
XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_FileLengthFrames, &size, &length), "Couldn't get file's length");
|
||||
return length;
|
||||
}
|
||||
|
||||
void SetNumberFrames(SInt64 length) {
|
||||
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_FileLengthFrames, sizeof(SInt64), &length), "Couldn't set file's length");
|
||||
}
|
||||
|
||||
void Seek(SInt64 pos) {
|
||||
XThrowIfError(ExtAudioFileSeek(mExtAF, pos), "Couldn't seek in audio file");
|
||||
}
|
||||
|
||||
SInt64 Tell() {
|
||||
SInt64 pos;
|
||||
XThrowIfError(ExtAudioFileTell(mExtAF, &pos), "Couldn't get file's mark");
|
||||
return pos;
|
||||
}
|
||||
|
||||
void Read(UInt32 &ioFrames, AudioBufferList *ioData) {
|
||||
XThrowIfError(ExtAudioFileRead(mExtAF, &ioFrames, ioData), "Couldn't read audio file");
|
||||
}
|
||||
|
||||
void Write(UInt32 inFrames, const AudioBufferList *inData) {
|
||||
XThrowIfError(ExtAudioFileWrite(mExtAF, inFrames, inData), "Couldn't write audio file");
|
||||
}
|
||||
|
||||
void SetIOBufferSizeBytes(UInt32 bufferSizeBytes) {
|
||||
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_IOBufferSizeBytes, sizeof(UInt32), &bufferSizeBytes), "Couldn't set audio file's I/O buffer size");
|
||||
}
|
||||
|
||||
private:
|
||||
const CAAudioChannelLayout & FetchChannelLayout(CAAudioChannelLayout &layoutObj, ExtAudioFilePropertyID propID) {
|
||||
UInt32 size;
|
||||
XThrowIfError(ExtAudioFileGetPropertyInfo(mExtAF, propID, &size, NULL), "Couldn't get info about channel layout");
|
||||
AudioChannelLayout *layout = (AudioChannelLayout *)malloc(size);
|
||||
OSStatus err = ExtAudioFileGetProperty(mExtAF, propID, &size, layout);
|
||||
if (err) {
|
||||
free(layout);
|
||||
XThrowIfError(err, "Couldn't get channel layout");
|
||||
}
|
||||
layoutObj = layout;
|
||||
free(layout);
|
||||
return layoutObj;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
ExtAudioFileRef mExtAF;
|
||||
|
||||
CAStreamBasicDescription mFileDataFormat;
|
||||
CAAudioChannelLayout mFileChannelLayout;
|
||||
|
||||
CAStreamBasicDescription mClientDataFormat;
|
||||
CAAudioChannelLayout mClientChannelLayout;
|
||||
#endif
|
||||
|
||||
#if !CAAF_USE_EXTAUDIOFILE
|
||||
CAAudioFile();
|
||||
virtual ~CAAudioFile();
|
||||
|
||||
// --- second-stage initializers ---
|
||||
// Use exactly one of the following:
|
||||
// - Open
|
||||
// - PrepareNew followed by Create
|
||||
// - Wrap
|
||||
|
||||
void Open(const FSRef &fsref);
|
||||
// open an existing file
|
||||
|
||||
void CreateNew(const FSRef &inParentDir, CFStringRef inFileName, AudioFileTypeID inFileType, const AudioStreamBasicDescription &inStreamDesc, const AudioChannelLayout *inChannelLayout=NULL);
|
||||
|
||||
void Wrap(AudioFileID fileID, bool forWriting);
|
||||
// use this to wrap an AudioFileID opened externally
|
||||
|
||||
// ---
|
||||
|
||||
void Close();
|
||||
// In case you want to close the file before the destructor executes
|
||||
|
||||
// --- Data formats ---
|
||||
|
||||
// Allow specifying the file's channel layout. Must be called before SetClientFormat.
|
||||
// When writing, the specified channel layout is written to the file (if the file format supports
|
||||
// the channel layout). When reading, the specified layout overrides the one read from the file,
|
||||
// if any.
|
||||
void SetFileChannelLayout(const CAAudioChannelLayout &layout);
|
||||
|
||||
// This specifies the data format which the client will use for reading/writing the file,
|
||||
// which may be different from the file's format. An AudioConverter is created if necessary.
|
||||
// The client format must be linear PCM.
|
||||
void SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout=NULL);
|
||||
void SetClientDataFormat(const CAStreamBasicDescription &dataFormat) { SetClientFormat(dataFormat, NULL); }
|
||||
void SetClientChannelLayout(const CAAudioChannelLayout &layout) { SetClientFormat(mClientDataFormat, &layout); }
|
||||
|
||||
// Wrapping the underlying converter, if there is one
|
||||
OSStatus SetConverterProperty(AudioConverterPropertyID inPropertyID,
|
||||
UInt32 inPropertyDataSize,
|
||||
const void * inPropertyData,
|
||||
bool inCanFail = false);
|
||||
void SetConverterConfig(CFArrayRef config) {
|
||||
SetConverterProperty(kAudioConverterPropertySettings, sizeof(config), &config); }
|
||||
CFArrayRef GetConverterConfig();
|
||||
|
||||
// --- I/O ---
|
||||
// All I/O is sequential, but you can seek to an arbitrary position when reading.
|
||||
// SeekToPacket and TellPacket's packet numbers are in the file's data format, not the client's.
|
||||
// However, ReadPackets/WritePackets use packet counts in the client data format.
|
||||
|
||||
void Read(UInt32 &ioNumFrames, AudioBufferList *ioData);
|
||||
void Write(UInt32 numFrames, const AudioBufferList *data);
|
||||
|
||||
// These can fail for files without a constant mFramesPerPacket
|
||||
void Seek(SInt64 frameNumber);
|
||||
SInt64 Tell() const; // frameNumber
|
||||
|
||||
// --- Accessors ---
|
||||
// note: client parameters only valid if SetClientFormat has been called
|
||||
AudioFileID GetAudioFileID() const { return mAudioFile; }
|
||||
const CAStreamBasicDescription &GetFileDataFormat() const { return mFileDataFormat; }
|
||||
const CAStreamBasicDescription &GetClientDataFormat() const { return mClientDataFormat; }
|
||||
const CAAudioChannelLayout & GetFileChannelLayout() const { return mFileChannelLayout; }
|
||||
const CAAudioChannelLayout & GetClientChannelLayout() const { return mClientChannelLayout; }
|
||||
AudioConverterRef GetConverter() const { return mConverter; }
|
||||
|
||||
UInt32 GetFileMaxPacketSize() const { return mFileMaxPacketSize; }
|
||||
UInt32 GetClientMaxPacketSize() const { return mClientMaxPacketSize; }
|
||||
SInt64 GetNumberPackets() const {
|
||||
SInt64 npackets;
|
||||
UInt32 propertySize = sizeof(npackets);
|
||||
XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyAudioDataPacketCount, &propertySize, &npackets), "get audio file's packet count");
|
||||
return npackets;
|
||||
}
|
||||
SInt64 GetNumberFrames() const;
|
||||
// will be 0 if the file's frames/packet is 0 (variable)
|
||||
void SetNumberFrames(SInt64 length); // should only be set on a PCM file
|
||||
|
||||
// --- Tunable performance parameters ---
|
||||
void SetUseCache(bool b) { mUseCache = b; }
|
||||
void SetIOBufferSizeBytes(UInt32 bufferSizeBytes) { mIOBufferSizeBytes = bufferSizeBytes; }
|
||||
UInt32 GetIOBufferSizeBytes() { return mIOBufferSizeBytes; }
|
||||
void * GetIOBuffer() { return mIOBufferList.mBuffers[0].mData; }
|
||||
void SetIOBuffer(void *buf);
|
||||
|
||||
// -- Profiling ---
|
||||
#if CAAUDIOFILE_PROFILE
|
||||
void EnableProfiling(bool b) { mProfiling = b; }
|
||||
UInt64 TicksInConverter() const { return (mTicksInConverter > 0) ? (mTicksInConverter - mTicksInReadInConverter) : 0; }
|
||||
UInt64 TicksInIO() const { return mTicksInIO; }
|
||||
#endif
|
||||
|
||||
// _______________________________________________________________________________________
|
||||
private:
|
||||
SInt64 FileDataOffset();
|
||||
void SeekToPacket(SInt64 packetNumber);
|
||||
SInt64 TellPacket() const { return mPacketMark; } // will be imprecise if SeekToFrame was called
|
||||
|
||||
void SetConverterChannelLayout(bool output, const CAAudioChannelLayout &layout);
|
||||
void WritePacketsFromCallback(
|
||||
AudioConverterComplexInputDataProc inInputDataProc,
|
||||
void * inInputDataProcUserData);
|
||||
// will use I/O buffer size
|
||||
void InitFileMaxPacketSize();
|
||||
void FileFormatChanged(const FSRef *parentDir=0, CFStringRef filename=0, AudioFileTypeID filetype=0);
|
||||
|
||||
void GetExistingFileInfo();
|
||||
void FlushEncoder();
|
||||
void CloseConverter();
|
||||
void UpdateClientMaxPacketSize();
|
||||
void AllocateBuffers(bool okToFail=false);
|
||||
SInt64 PacketToFrame(SInt64 packet) const;
|
||||
SInt64 FrameToPacket(SInt64 inFrame) const;
|
||||
|
||||
static OSStatus ReadInputProc( AudioConverterRef inAudioConverter,
|
||||
UInt32* ioNumberDataPackets,
|
||||
AudioBufferList* ioData,
|
||||
AudioStreamPacketDescription** outDataPacketDescription,
|
||||
void* inUserData);
|
||||
|
||||
static OSStatus WriteInputProc( AudioConverterRef inAudioConverter,
|
||||
UInt32* ioNumberDataPackets,
|
||||
AudioBufferList* ioData,
|
||||
AudioStreamPacketDescription** outDataPacketDescription,
|
||||
void* inUserData);
|
||||
// _______________________________________________________________________________________
|
||||
private:
|
||||
|
||||
// the file
|
||||
FSRef mFSRef;
|
||||
AudioFileID mAudioFile;
|
||||
bool mOwnOpenFile;
|
||||
bool mUseCache;
|
||||
bool mFinishingEncoding;
|
||||
enum { kClosed, kReading, kPreparingToCreate, kPreparingToWrite, kWriting } mMode;
|
||||
|
||||
// SInt64 mNumberPackets; // in file's format
|
||||
SInt64 mFileDataOffset;
|
||||
SInt64 mPacketMark; // in file's format
|
||||
SInt64 mFrameMark; // this may be offset from the start of the file
|
||||
// by the codec's latency; i.e. our frame 0 could
|
||||
// lie at frame 2112 of a decoded AAC file
|
||||
SInt32 mFrame0Offset;
|
||||
UInt32 mFramesToSkipFollowingSeek;
|
||||
|
||||
// buffers
|
||||
UInt32 mIOBufferSizeBytes;
|
||||
UInt32 mIOBufferSizePackets;
|
||||
AudioBufferList mIOBufferList; // only one buffer -- USE ACCESSOR so it can be lazily initialized
|
||||
bool mClientOwnsIOBuffer;
|
||||
AudioStreamPacketDescription *mPacketDescs;
|
||||
UInt32 mNumPacketDescs;
|
||||
|
||||
// formats/conversion
|
||||
AudioConverterRef mConverter;
|
||||
CAStreamBasicDescription mFileDataFormat;
|
||||
CAStreamBasicDescription mClientDataFormat;
|
||||
CAAudioChannelLayout mFileChannelLayout;
|
||||
CAAudioChannelLayout mClientChannelLayout;
|
||||
UInt32 mFileMaxPacketSize;
|
||||
UInt32 mClientMaxPacketSize;
|
||||
|
||||
// cookie
|
||||
Byte * mMagicCookie;
|
||||
UInt32 mMagicCookieSize;
|
||||
|
||||
// for ReadPackets
|
||||
UInt32 mMaxPacketsToRead;
|
||||
|
||||
// for WritePackets
|
||||
UInt32 mWritePackets;
|
||||
CABufferList * mWriteBufferList;
|
||||
|
||||
#if CAAUDIOFILE_PROFILE
|
||||
// performance
|
||||
bool mProfiling;
|
||||
UInt64 mTicksInConverter;
|
||||
UInt64 mTicksInReadInConverter;
|
||||
UInt64 mTicksInIO;
|
||||
bool mInConverter;
|
||||
#endif
|
||||
|
||||
#endif // CAAF_USE_EXTAUDIOFILE
|
||||
};
|
||||
|
||||
#endif // __CAAudioFile_h__
|
||||
179
libs/appleutility/CABufferList.cpp
Normal file
179
libs/appleutility/CABufferList.cpp
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
|
||||
copyrights in this original Apple software (the "Apple Software"), to use,
|
||||
reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions of
|
||||
the Apple Software. Neither the name, trademarks, service marks or logos of
|
||||
Apple Computer, Inc. may be used to endorse or promote products derived from the
|
||||
Apple Software without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or implied,
|
||||
are granted by Apple herein, including but not limited to any patent rights that
|
||||
may be infringed by your derivative works or by other works in which the Apple
|
||||
Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
|
||||
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
|
||||
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*=============================================================================
|
||||
CABufferList.cpp
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "CABufferList.h"
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#else
|
||||
#include <Endian.h>
|
||||
#endif
|
||||
|
||||
void CABufferList::AllocateBuffers(UInt32 nBytes)
|
||||
{
|
||||
if (nBytes <= GetNumBytes()) return;
|
||||
|
||||
if (mNumberBuffers > 1)
|
||||
// align successive buffers for Altivec and to take alternating
|
||||
// cache line hits by spacing them by odd multiples of 16
|
||||
nBytes = (nBytes + (0x10 - (nBytes & 0xF))) | 0x10;
|
||||
UInt32 memorySize = nBytes * mNumberBuffers;
|
||||
Byte *newMemory = new Byte[memorySize], *p = newMemory;
|
||||
memset(newMemory, 0, memorySize); // get page faults now, not later
|
||||
|
||||
AudioBuffer *buf = mBuffers;
|
||||
for (UInt32 i = mNumberBuffers; i--; ++buf) {
|
||||
if (buf->mData != NULL && buf->mDataByteSize > 0)
|
||||
// preserve existing buffer contents
|
||||
memcpy(p, buf->mData, buf->mDataByteSize);
|
||||
buf->mDataByteSize = nBytes;
|
||||
buf->mData = p;
|
||||
p += nBytes;
|
||||
}
|
||||
Byte *oldMemory = mBufferMemory;
|
||||
mBufferMemory = newMemory;
|
||||
delete[] oldMemory;
|
||||
}
|
||||
|
||||
void CABufferList::AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inSrcList, CABufferList *inSetPtrList)
|
||||
{
|
||||
if (mNumberBuffers != inSrcList->mNumberBuffers) return;
|
||||
if (mNumberBuffers != inSetPtrList->mNumberBuffers) return;
|
||||
if (nBytes <= GetNumBytes()) {
|
||||
CopyAllFrom(inSrcList, inSetPtrList);
|
||||
return;
|
||||
}
|
||||
inSetPtrList->VerifyNotTrashingOwnedBuffer();
|
||||
UInt32 fromByteSize = inSrcList->GetNumBytes();
|
||||
|
||||
if (mNumberBuffers > 1)
|
||||
// align successive buffers for Altivec and to take alternating
|
||||
// cache line hits by spacing them by odd multiples of 16
|
||||
nBytes = (nBytes + (0x10 - (nBytes & 0xF))) | 0x10;
|
||||
UInt32 memorySize = nBytes * mNumberBuffers;
|
||||
Byte *newMemory = new Byte[memorySize], *p = newMemory;
|
||||
memset(newMemory, 0, memorySize); // make buffer "hot"
|
||||
|
||||
AudioBuffer *buf = mBuffers;
|
||||
AudioBuffer *ptrBuf = inSetPtrList->mBuffers;
|
||||
AudioBuffer *srcBuf = inSrcList->mBuffers;
|
||||
for (UInt32 i = mNumberBuffers; i--; ++buf, ++ptrBuf, ++srcBuf) {
|
||||
if (srcBuf->mData != NULL && srcBuf->mDataByteSize > 0)
|
||||
// preserve existing buffer contents
|
||||
memmove(p, srcBuf->mData, srcBuf->mDataByteSize);
|
||||
buf->mDataByteSize = nBytes;
|
||||
buf->mData = p;
|
||||
ptrBuf->mDataByteSize = srcBuf->mDataByteSize;
|
||||
ptrBuf->mData = p;
|
||||
p += nBytes;
|
||||
}
|
||||
Byte *oldMemory = mBufferMemory;
|
||||
mBufferMemory = newMemory;
|
||||
if (inSrcList != inSetPtrList)
|
||||
inSrcList->BytesConsumed(fromByteSize);
|
||||
delete[] oldMemory;
|
||||
}
|
||||
|
||||
void CABufferList::DeallocateBuffers()
|
||||
{
|
||||
AudioBuffer *buf = mBuffers;
|
||||
for (UInt32 i = mNumberBuffers; i--; ++buf) {
|
||||
buf->mData = NULL;
|
||||
buf->mDataByteSize = 0;
|
||||
}
|
||||
if (mBufferMemory != NULL) {
|
||||
delete[] mBufferMemory;
|
||||
mBufferMemory = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize)
|
||||
{
|
||||
printf("AudioBufferList @ %p:\n", abl);
|
||||
const AudioBuffer *buf = abl->mBuffers;
|
||||
for (UInt32 i = 0; i < abl->mNumberBuffers; ++i, ++buf) {
|
||||
printf(" [%2ld]: %2ldch, %5ld bytes @ %8p",
|
||||
i, buf->mNumberChannels, buf->mDataByteSize, buf->mData);
|
||||
if (framesToPrint) {
|
||||
printf(":");
|
||||
Byte *p = (Byte *)buf->mData;
|
||||
for (int j = framesToPrint * buf->mNumberChannels; --j >= 0; )
|
||||
switch (wordSize) {
|
||||
case 0:
|
||||
printf(" %6.3f", *(Float32 *)p);
|
||||
p += sizeof(Float32);
|
||||
break;
|
||||
case 1:
|
||||
case -1:
|
||||
printf(" %02X", *p);
|
||||
p += 1;
|
||||
break;
|
||||
case 2:
|
||||
printf(" %04X", EndianU16_BtoN(*(UInt16 *)p));
|
||||
p += 2;
|
||||
break;
|
||||
case 3:
|
||||
printf(" %06X", (p[0] << 16) | (p[1] << 8) | p[2]);
|
||||
p += 3;
|
||||
break;
|
||||
case 4:
|
||||
printf(" %08lX", EndianU32_BtoN(*(UInt32 *)p));
|
||||
p += 4;
|
||||
break;
|
||||
case -2:
|
||||
printf(" %04X", EndianU16_LtoN(*(UInt16 *)p));
|
||||
p += 2;
|
||||
break;
|
||||
case -3:
|
||||
printf(" %06X", (p[2] << 16) | (p[1] << 8) | p[0]);
|
||||
p += 3;
|
||||
break;
|
||||
case -4:
|
||||
printf(" %08lX", EndianU32_LtoN(*(UInt32 *)p));
|
||||
p += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
300
libs/appleutility/CABufferList.h
Normal file
300
libs/appleutility/CABufferList.h
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
|
||||
copyrights in this original Apple software (the "Apple Software"), to use,
|
||||
reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions of
|
||||
the Apple Software. Neither the name, trademarks, service marks or logos of
|
||||
Apple Computer, Inc. may be used to endorse or promote products derived from the
|
||||
Apple Software without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or implied,
|
||||
are granted by Apple herein, including but not limited to any patent rights that
|
||||
may be infringed by your derivative works or by other works in which the Apple
|
||||
Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
|
||||
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
|
||||
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*=============================================================================
|
||||
CABufferList.h
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef __CABufferList_h__
|
||||
#define __CABufferList_h__
|
||||
|
||||
#include <stddef.h>
|
||||
#include "CAStreamBasicDescription.h"
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#else
|
||||
#include <AssertMacros.h>
|
||||
#endif
|
||||
|
||||
extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize);
|
||||
// wordSize: 0 = float32, else integer word size, negative if little-endian
|
||||
|
||||
/* ____________________________________________________________________________
|
||||
// CABufferList - variable length buffer list
|
||||
|
||||
This class is designed for use in non-simplistic cases. For AudioUnits, AUBufferList
|
||||
is preferred.
|
||||
|
||||
CABufferList can be used in one of two ways:
|
||||
- as mutable pointers into non-owned memory
|
||||
- as an immutable array of buffers (owns its own memory).
|
||||
|
||||
All buffers are assumed to have the same format (number of channels, word size), so that
|
||||
we can assume their mDataByteSizes are all the same.
|
||||
____________________________________________________________________________ */
|
||||
class CABufferList {
|
||||
public:
|
||||
void * operator new(size_t /*size*/, int nBuffers) {
|
||||
return ::operator new(sizeof(CABufferList) + (nBuffers-1) * sizeof(AudioBuffer));
|
||||
}
|
||||
static CABufferList * New(const char *name, const CAStreamBasicDescription &format)
|
||||
{
|
||||
UInt32 numBuffers = format.NumberChannelStreams(), channelsPerBuffer = format.NumberInterleavedChannels();
|
||||
return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer);
|
||||
}
|
||||
|
||||
protected:
|
||||
CABufferList(const char *name, UInt32 numBuffers, UInt32 channelsPerBuffer) :
|
||||
mName(name),
|
||||
mBufferMemory(NULL)
|
||||
{
|
||||
check(numBuffers > 0 /*&& channelsPerBuffer > 0*/);
|
||||
mNumberBuffers = numBuffers;
|
||||
AudioBuffer *buf = mBuffers;
|
||||
for (UInt32 i = mNumberBuffers; i--; ++buf) {
|
||||
buf->mNumberChannels = channelsPerBuffer;
|
||||
buf->mDataByteSize = 0;
|
||||
buf->mData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
~CABufferList()
|
||||
{
|
||||
if (mBufferMemory)
|
||||
delete[] mBufferMemory;
|
||||
}
|
||||
|
||||
const char * Name() { return mName; }
|
||||
|
||||
const AudioBufferList & GetBufferList() const { return *(AudioBufferList *)&mNumberBuffers; }
|
||||
|
||||
AudioBufferList & GetModifiableBufferList()
|
||||
{
|
||||
VerifyNotTrashingOwnedBuffer();
|
||||
return _GetBufferList();
|
||||
}
|
||||
|
||||
UInt32 GetNumBytes() const
|
||||
{
|
||||
return mBuffers[0].mDataByteSize;
|
||||
}
|
||||
|
||||
void SetBytes(UInt32 nBytes, void *data)
|
||||
{
|
||||
VerifyNotTrashingOwnedBuffer();
|
||||
check(mNumberBuffers == 1);
|
||||
mBuffers[0].mDataByteSize = nBytes;
|
||||
mBuffers[0].mData = data;
|
||||
}
|
||||
|
||||
void CopyAllFrom(CABufferList *srcbl, CABufferList *ptrbl)
|
||||
// copies bytes from srcbl
|
||||
// make ptrbl reflect the length copied
|
||||
// note that srcbl may be same as ptrbl!
|
||||
{
|
||||
// Note that this buffer *can* own memory and its pointers/lengths are not
|
||||
// altered; only its buffer contents, which are copied from srcbl.
|
||||
// The pointers/lengths in ptrbl are updated to reflect the addresses/lengths
|
||||
// of the copied data, and srcbl's contents are consumed.
|
||||
ptrbl->VerifyNotTrashingOwnedBuffer();
|
||||
UInt32 nBytes = srcbl->GetNumBytes();
|
||||
AudioBuffer *mybuf = mBuffers, *srcbuf = srcbl->mBuffers,
|
||||
*ptrbuf = ptrbl->mBuffers;
|
||||
for (UInt32 i = mNumberBuffers; i--; ++mybuf, ++srcbuf, ++ptrbuf) {
|
||||
memmove(mybuf->mData, srcbuf->mData, srcbuf->mDataByteSize);
|
||||
ptrbuf->mData = mybuf->mData;
|
||||
ptrbuf->mDataByteSize = srcbuf->mDataByteSize;
|
||||
}
|
||||
if (srcbl != ptrbl)
|
||||
srcbl->BytesConsumed(nBytes);
|
||||
}
|
||||
|
||||
void AppendFrom(CABufferList *blp, UInt32 nBytes)
|
||||
{
|
||||
VerifyNotTrashingOwnedBuffer();
|
||||
AudioBuffer *mybuf = mBuffers, *srcbuf = blp->mBuffers;
|
||||
for (UInt32 i = mNumberBuffers; i--; ++mybuf, ++srcbuf) {
|
||||
check(nBytes <= srcbuf->mDataByteSize);
|
||||
memcpy((Byte *)mybuf->mData + mybuf->mDataByteSize, srcbuf->mData, nBytes);
|
||||
mybuf->mDataByteSize += nBytes;
|
||||
}
|
||||
blp->BytesConsumed(nBytes);
|
||||
}
|
||||
|
||||
void PadWithZeroes(UInt32 desiredBufferSize)
|
||||
// for cases where an algorithm (e.g. SRC) requires some
|
||||
// padding to create silence following end-of-file
|
||||
{
|
||||
VerifyNotTrashingOwnedBuffer();
|
||||
if (GetNumBytes() > desiredBufferSize) return;
|
||||
AudioBuffer *buf = mBuffers;
|
||||
for (UInt32 i = mNumberBuffers; i--; ++buf) {
|
||||
memset((Byte *)buf->mData + buf->mDataByteSize, 0, desiredBufferSize - buf->mDataByteSize);
|
||||
buf->mDataByteSize = desiredBufferSize;
|
||||
}
|
||||
}
|
||||
|
||||
void SetToZeroes(UInt32 nBytes)
|
||||
{
|
||||
VerifyNotTrashingOwnedBuffer();
|
||||
AudioBuffer *buf = mBuffers;
|
||||
for (UInt32 i = mNumberBuffers; i--; ++buf) {
|
||||
memset((Byte *)buf->mData, 0, nBytes);
|
||||
buf->mDataByteSize = nBytes;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
DeallocateBuffers();
|
||||
}
|
||||
|
||||
Boolean SameDataAs(const CABufferList* anotherBufferList)
|
||||
{
|
||||
// check to see if two buffer lists point to the same memory.
|
||||
if (mNumberBuffers != anotherBufferList->mNumberBuffers) return false;
|
||||
|
||||
for (UInt32 i = 0; i < mNumberBuffers; ++i) {
|
||||
if (mBuffers[i].mData != anotherBufferList->mBuffers[i].mData) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void BytesConsumed(UInt32 nBytes)
|
||||
// advance buffer pointers, decrease buffer sizes
|
||||
{
|
||||
VerifyNotTrashingOwnedBuffer();
|
||||
AudioBuffer *buf = mBuffers;
|
||||
for (UInt32 i = mNumberBuffers; i--; ++buf) {
|
||||
check(nBytes <= buf->mDataByteSize);
|
||||
buf->mData = (Byte *)buf->mData + nBytes;
|
||||
buf->mDataByteSize -= nBytes;
|
||||
}
|
||||
}
|
||||
|
||||
void SetFrom(const AudioBufferList *abl)
|
||||
{
|
||||
VerifyNotTrashingOwnedBuffer();
|
||||
memcpy(&_GetBufferList(), abl, (char *)&abl->mBuffers[abl->mNumberBuffers] - (char *)abl);
|
||||
}
|
||||
|
||||
void SetFrom(const CABufferList *blp)
|
||||
{
|
||||
SetFrom(&blp->GetBufferList());
|
||||
}
|
||||
|
||||
void SetFrom(const AudioBufferList *abl, UInt32 nBytes)
|
||||
{
|
||||
VerifyNotTrashingOwnedBuffer();
|
||||
AudioBuffer *mybuf = mBuffers;
|
||||
const AudioBuffer *srcbuf = abl->mBuffers;
|
||||
for (UInt32 i = mNumberBuffers; i--; ++mybuf, ++srcbuf) {
|
||||
mybuf->mNumberChannels = srcbuf->mNumberChannels;
|
||||
mybuf->mDataByteSize = nBytes;
|
||||
mybuf->mData = srcbuf->mData;
|
||||
}
|
||||
}
|
||||
|
||||
void SetFrom(const CABufferList *blp, UInt32 nBytes)
|
||||
{
|
||||
SetFrom(&blp->GetBufferList(), nBytes);
|
||||
}
|
||||
|
||||
AudioBufferList * ToAudioBufferList(AudioBufferList *abl) const
|
||||
{
|
||||
memcpy(abl, &GetBufferList(), (char *)&abl->mBuffers[mNumberBuffers] - (char *)abl);
|
||||
return abl;
|
||||
}
|
||||
|
||||
void AllocateBuffers(UInt32 nBytes);
|
||||
void AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inCopyFromList, CABufferList *inSetPtrList);
|
||||
|
||||
void DeallocateBuffers();
|
||||
|
||||
void UseExternalBuffer(Byte *ptr, UInt32 nBytes);
|
||||
|
||||
void AdvanceBufferPointers(UInt32 nBytes)
|
||||
// this is for bufferlists that function simply as
|
||||
// an array of pointers into another bufferlist, being advanced,
|
||||
// as in RenderOutput implementations
|
||||
{
|
||||
VerifyNotTrashingOwnedBuffer();
|
||||
AudioBuffer *buf = mBuffers;
|
||||
for (UInt32 i = mNumberBuffers; i--; ++buf) {
|
||||
buf->mData = (Byte *)buf->mData + nBytes;
|
||||
buf->mDataByteSize -= nBytes;
|
||||
}
|
||||
}
|
||||
|
||||
void SetNumBytes(UInt32 nBytes)
|
||||
{
|
||||
VerifyNotTrashingOwnedBuffer();
|
||||
AudioBuffer *buf = mBuffers;
|
||||
for (UInt32 i = mNumberBuffers; i--; ++buf)
|
||||
buf->mDataByteSize = nBytes;
|
||||
}
|
||||
|
||||
void Print(const char *label=NULL, int nframes=0, int wordSize=0) const
|
||||
{
|
||||
if (label == NULL)
|
||||
label = mName;
|
||||
printf("%s - ", label);
|
||||
CAShowAudioBufferList(&GetBufferList(), nframes, wordSize);
|
||||
if (mBufferMemory)
|
||||
printf(" owned memory @ 0x%p:\n", mBufferMemory);
|
||||
}
|
||||
|
||||
protected:
|
||||
AudioBufferList & _GetBufferList() { return *(AudioBufferList *)&mNumberBuffers; } // use with care
|
||||
// if we make this public, then we lose ability to call VerifyNotTrashingOwnedBuffer
|
||||
void VerifyNotTrashingOwnedBuffer()
|
||||
{
|
||||
// This needs to be called from places where we are modifying the buffer list.
|
||||
// It's an error to modify the buffer pointers or lengths if we own the buffer memory.
|
||||
check(mBufferMemory == NULL);
|
||||
}
|
||||
|
||||
const char * mName; // for debugging
|
||||
Byte * mBufferMemory;
|
||||
// the rest must exactly mirror the structure of AudioBufferList
|
||||
UInt32 mNumberBuffers;
|
||||
AudioBuffer mBuffers[1];
|
||||
};
|
||||
|
||||
#endif // __CABufferList_h__
|
||||
45
libs/appleutility/CAXException.cpp
Normal file
45
libs/appleutility/CAXException.cpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
|
||||
copyrights in this original Apple software (the "Apple Software"), to use,
|
||||
reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions of
|
||||
the Apple Software. Neither the name, trademarks, service marks or logos of
|
||||
Apple Computer, Inc. may be used to endorse or promote products derived from the
|
||||
Apple Software without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or implied,
|
||||
are granted by Apple herein, including but not limited to any patent rights that
|
||||
may be infringed by your derivative works or by other works in which the Apple
|
||||
Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
|
||||
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
|
||||
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*=============================================================================
|
||||
CAXException.cpp
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "CAXException.h"
|
||||
|
||||
CAXException::WarningHandler CAXException::sWarningHandler = NULL;
|
||||
158
libs/appleutility/CAXException.h
Normal file
158
libs/appleutility/CAXException.h
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved.
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
|
||||
copyrights in this original Apple software (the "Apple Software"), to use,
|
||||
reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions of
|
||||
the Apple Software. Neither the name, trademarks, service marks or logos of
|
||||
Apple Computer, Inc. may be used to endorse or promote products derived from the
|
||||
Apple Software without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or implied,
|
||||
are granted by Apple herein, including but not limited to any patent rights that
|
||||
may be infringed by your derivative works or by other works in which the Apple
|
||||
Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
|
||||
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
|
||||
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*=============================================================================
|
||||
CAXException.h
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef __CAXException_h__
|
||||
#define __CAXException_h__
|
||||
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#else
|
||||
#include <ConditionalMacros.h>
|
||||
#include <CoreServices.h>
|
||||
#endif
|
||||
#include "CADebugMacros.h"
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
// An extended exception class that includes the name of the failed operation
|
||||
class CAXException {
|
||||
public:
|
||||
CAXException(const char *operation, OSStatus err) :
|
||||
mError(err)
|
||||
{
|
||||
if (operation == NULL)
|
||||
mOperation[0] = '\0';
|
||||
else if (strlen(operation) >= sizeof(mOperation)) {
|
||||
memcpy(mOperation, operation, sizeof(mOperation) - 1);
|
||||
mOperation[sizeof(mOperation) - 1] = '\0';
|
||||
} else
|
||||
strcpy(mOperation, operation);
|
||||
}
|
||||
|
||||
char *FormatError(char *str) const
|
||||
{
|
||||
return FormatError(str, mError);
|
||||
}
|
||||
|
||||
char mOperation[256];
|
||||
const OSStatus mError;
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
typedef void (*WarningHandler)(const char *msg, OSStatus err);
|
||||
|
||||
/*static void Throw(const char *operation, OSStatus err)
|
||||
{
|
||||
throw CAXException(operation, err);
|
||||
}*/
|
||||
|
||||
static char *FormatError(char *str, OSStatus error)
|
||||
{
|
||||
// see if it appears to be a 4-char-code
|
||||
*(UInt32 *)(str + 1) = EndianU32_NtoB(error);
|
||||
if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {
|
||||
str[0] = str[5] = '\'';
|
||||
str[6] = '\0';
|
||||
} else
|
||||
// no, format it as an integer
|
||||
sprintf(str, "%ld", error);
|
||||
return str;
|
||||
}
|
||||
|
||||
static void Warning(const char *s, OSStatus error)
|
||||
{
|
||||
if (sWarningHandler)
|
||||
(*sWarningHandler)(s, error);
|
||||
}
|
||||
|
||||
static void SetWarningHandler(WarningHandler f) { sWarningHandler = f; }
|
||||
private:
|
||||
static WarningHandler sWarningHandler;
|
||||
};
|
||||
|
||||
#if DEBUG || CoreAudio_Debug
|
||||
#define XThrowIfError(error, operation) \
|
||||
do { \
|
||||
OSStatus __err = error; \
|
||||
if (__err) { \
|
||||
char __buf[12]; \
|
||||
DebugMessageN2("error %s: %4s\n", CAXException::FormatError(__buf, __err), operation);\
|
||||
STOP; \
|
||||
throw CAXException(operation, __err); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define XThrowIf(condition, error, operation) \
|
||||
do { \
|
||||
if (condition) { \
|
||||
OSStatus __err = error; \
|
||||
char __buf[12]; \
|
||||
DebugMessageN2("error %s: %4s\n", CAXException::FormatError(__buf, __err), operation);\
|
||||
STOP; \
|
||||
throw CAXException(operation, __err); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define XThrowIfError(error, operation) \
|
||||
do { \
|
||||
OSStatus __err = error; \
|
||||
if (__err) { \
|
||||
throw CAXException(operation, __err); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define XThrowIf(condition, error, operation) \
|
||||
do { \
|
||||
if (condition) { \
|
||||
OSStatus __err = error; \
|
||||
throw CAXException(operation, __err); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#define XThrow(error, operation) XThrowIf(true, error, operation)
|
||||
#define XThrowIfErr(error) XThrowIfError(error, #error)
|
||||
|
||||
#endif // __CAXException_h__
|
||||
|
|
@ -20,8 +20,9 @@
|
|||
#ifndef __coreaudio_source_h__
|
||||
#define __coreaudio_source_h__
|
||||
|
||||
#include <appleutility/CAAudioFile.h>
|
||||
|
||||
#include <ardour/audiofilesource.h>
|
||||
#include <AudioToolbox/ExtendedAudioFile.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
|
|
@ -45,7 +46,7 @@ class CoreAudioSource : public AudioFileSource {
|
|||
|
||||
|
||||
private:
|
||||
ExtAudioFileRef af;
|
||||
mutable CAAudioFile af;
|
||||
uint16_t n_channels;
|
||||
|
||||
mutable float *tmpbuf;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@
|
|||
#include <pbd/error.h>
|
||||
#include <ardour/coreaudiosource.h>
|
||||
|
||||
#include <appleutility/CAAudioFile.h>
|
||||
#include <appleutility/CAStreamBasicDescription.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
#include <AudioToolbox/AudioFormat.h>
|
||||
|
|
@ -43,93 +46,48 @@ void
|
|||
CoreAudioSource::init (const string& idstr)
|
||||
{
|
||||
string::size_type pos;
|
||||
string file;
|
||||
|
||||
tmpbuf = 0;
|
||||
tmpbufsize = 0;
|
||||
af = 0;
|
||||
OSStatus err = noErr;
|
||||
|
||||
_name = idstr;
|
||||
|
||||
if ((pos = idstr.find_last_of (':')) == string::npos) {
|
||||
channel = 0;
|
||||
file = idstr;
|
||||
_path = idstr;
|
||||
} else {
|
||||
channel = atoi (idstr.substr (pos+1).c_str());
|
||||
file = idstr.substr (0, pos);
|
||||
_path = idstr.substr (0, pos);
|
||||
}
|
||||
|
||||
cerr << "CoreAudioSource::init() " << name() << endl;
|
||||
|
||||
/* note that we temporarily truncated _id at the colon */
|
||||
FSRef fsr;
|
||||
err = FSPathMakeRef ((UInt8*)file.c_str(), &fsr, 0);
|
||||
if (err != noErr) {
|
||||
error << string_compose (_("Could not make reference to file: %1"), name()) << endmsg;
|
||||
throw failed_constructor();
|
||||
}
|
||||
try {
|
||||
af.Open(_path.c_str());
|
||||
|
||||
err = ExtAudioFileOpen (&fsr, &af);
|
||||
if (err != noErr) {
|
||||
error << string_compose (_("Could not open file: %1"), name()) << endmsg;
|
||||
ExtAudioFileDispose (af);
|
||||
throw failed_constructor();
|
||||
}
|
||||
CAStreamBasicDescription file_asbd (af.GetFileDataFormat());
|
||||
n_channels = file_asbd.NumberChannels();
|
||||
cerr << "number of channels: " << n_channels << endl;
|
||||
|
||||
AudioStreamBasicDescription file_asbd;
|
||||
memset(&file_asbd, 0, sizeof(AudioStreamBasicDescription));
|
||||
size_t asbd_size = sizeof(AudioStreamBasicDescription);
|
||||
err = ExtAudioFileGetProperty(af,
|
||||
kExtAudioFileProperty_FileDataFormat, &asbd_size, &file_asbd);
|
||||
if (err != noErr) {
|
||||
error << string_compose (_("Could not get file data format for file: %1"), name()) << endmsg;
|
||||
ExtAudioFileDispose (af);
|
||||
throw failed_constructor();
|
||||
}
|
||||
n_channels = file_asbd.mChannelsPerFrame;
|
||||
if (channel >= n_channels) {
|
||||
error << string_compose("CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel number (%3)", n_channels, channel, name()) << endmsg;
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
cerr << "number of channels: " << n_channels << endl;
|
||||
_length = af.GetNumberFrames();
|
||||
|
||||
if (channel >= n_channels) {
|
||||
error << string_compose(_("CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel number"), n_channels, channel) << endmsg;
|
||||
ExtAudioFileDispose (af);
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
int64_t ca_frames;
|
||||
size_t prop_size = sizeof(int64_t);
|
||||
|
||||
err = ExtAudioFileGetProperty(af, kExtAudioFileProperty_FileLengthFrames, &prop_size, &ca_frames);
|
||||
if (err != noErr) {
|
||||
error << string_compose (_("Could not get file length for file: %1"), name()) << endmsg;
|
||||
ExtAudioFileDispose (af);
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
_length = ca_frames;
|
||||
_path = file;
|
||||
|
||||
AudioStreamBasicDescription client_asbd;
|
||||
memset(&client_asbd, 0, sizeof(AudioStreamBasicDescription));
|
||||
client_asbd.mSampleRate = file_asbd.mSampleRate;
|
||||
client_asbd.mFormatID = kAudioFormatLinearPCM;
|
||||
client_asbd.mFormatFlags = kLinearPCMFormatFlagIsFloat;
|
||||
client_asbd.mBytesPerPacket = file_asbd.mChannelsPerFrame * 4;
|
||||
client_asbd.mFramesPerPacket = 1;
|
||||
client_asbd.mBytesPerFrame = client_asbd.mBytesPerPacket;
|
||||
client_asbd.mChannelsPerFrame = file_asbd.mChannelsPerFrame;
|
||||
client_asbd.mBitsPerChannel = 32;
|
||||
|
||||
err = ExtAudioFileSetProperty (af, kExtAudioFileProperty_ClientDataFormat, asbd_size, &client_asbd);
|
||||
if (err != noErr) {
|
||||
error << string_compose (_("Could not set client data format for file: %1"), name()) << endmsg;
|
||||
ExtAudioFileDispose (af);
|
||||
CAStreamBasicDescription client_asbd(file_asbd);
|
||||
client_asbd.SetCanonical(client_asbd.NumberChannels(), false);
|
||||
af.SetClientFormat (client_asbd);
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose ("CoreAudioSource: %1 (%2)", cax.mOperation, name()) << endmsg;
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
if (_build_peakfiles) {
|
||||
if (initialize_peakfile (false, file)) {
|
||||
error << string_compose(_("initialize peakfile failed for file %1"), name()) << endmsg;
|
||||
ExtAudioFileDispose (af);
|
||||
if (initialize_peakfile (false, _path)) {
|
||||
error << string_compose("CoreAudioSource: initialize peakfile failed (%1)", name()) << endmsg;
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
|
@ -137,41 +95,44 @@ CoreAudioSource::init (const string& idstr)
|
|||
|
||||
CoreAudioSource::~CoreAudioSource ()
|
||||
{
|
||||
cerr << "CoreAudioSource::~CoreAudioSource() " << name() << endl;
|
||||
GoingAway (); /* EMIT SIGNAL */
|
||||
|
||||
if (af) {
|
||||
ExtAudioFileDispose (af);
|
||||
}
|
||||
|
||||
if (tmpbuf) {
|
||||
delete [] tmpbuf;
|
||||
}
|
||||
|
||||
cerr << "deletion done" << endl;
|
||||
}
|
||||
|
||||
jack_nframes_t
|
||||
CoreAudioSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const
|
||||
{
|
||||
OSStatus err = noErr;
|
||||
|
||||
err = ExtAudioFileSeek(af, start);
|
||||
if (err != noErr) {
|
||||
error << string_compose(_("CoreAudioSource: could not seek to frame %1 within %2 (%3)"), start, _name.substr (1), err) << endmsg;
|
||||
try {
|
||||
af.Seek (start);
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose("CoreAudioSource: %1 to %2 (%3)", cax.mOperation, start, _name.substr (1)) << endmsg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
AudioBufferList abl;
|
||||
abl.mNumberBuffers = 1;
|
||||
abl.mBuffers[0].mNumberChannels = n_channels;
|
||||
abl.mBuffers[0].mDataByteSize = cnt * sizeof(Sample);
|
||||
abl.mBuffers[0].mData = dst;
|
||||
|
||||
UInt32 new_cnt = cnt;
|
||||
if (n_channels == 1) {
|
||||
err = ExtAudioFileRead(af, (UInt32*) &cnt, &abl);
|
||||
_read_data_count = cnt * sizeof(float);
|
||||
return cnt;
|
||||
abl.mBuffers[0].mDataByteSize = cnt * sizeof(Sample);
|
||||
abl.mBuffers[0].mData = dst;
|
||||
try {
|
||||
af.Read (new_cnt, &abl);
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name);
|
||||
}
|
||||
_read_data_count = new_cnt * sizeof(float);
|
||||
return new_cnt;
|
||||
}
|
||||
|
||||
uint32_t real_cnt = cnt * n_channels;
|
||||
UInt32 real_cnt = cnt * n_channels;
|
||||
|
||||
{
|
||||
Glib::Mutex::Lock lm (_tmpbuf_lock);
|
||||
|
|
@ -185,10 +146,16 @@ CoreAudioSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_
|
|||
tmpbuf = new float[tmpbufsize];
|
||||
}
|
||||
|
||||
abl.mBuffers[0].mDataByteSize = real_cnt * sizeof(Sample);
|
||||
abl.mBuffers[0].mDataByteSize = tmpbufsize * sizeof(Sample);
|
||||
abl.mBuffers[0].mData = tmpbuf;
|
||||
|
||||
err = ExtAudioFileRead(af, (UInt32*) &real_cnt, &abl);
|
||||
cerr << "channel: " << channel << endl;
|
||||
|
||||
try {
|
||||
af.Read (real_cnt, &abl);
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name);
|
||||
}
|
||||
float *ptr = tmpbuf + channel;
|
||||
real_cnt /= n_channels;
|
||||
|
||||
|
|
@ -208,15 +175,12 @@ CoreAudioSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_
|
|||
float
|
||||
CoreAudioSource::sample_rate() const
|
||||
{
|
||||
AudioStreamBasicDescription client_asbd;
|
||||
memset(&client_asbd, 0, sizeof(AudioStreamBasicDescription));
|
||||
CAStreamBasicDescription client_asbd;
|
||||
|
||||
OSStatus err = noErr;
|
||||
size_t asbd_size = sizeof(AudioStreamBasicDescription);
|
||||
|
||||
err = ExtAudioFileSetProperty (af, kExtAudioFileProperty_ClientDataFormat, asbd_size, &client_asbd);
|
||||
if (err != noErr) {
|
||||
error << string_compose(_("Could not detect samplerate for: %1"), name()) << endmsg;
|
||||
try {
|
||||
client_asbd = af.GetClientDataFormat ();
|
||||
} catch (CAXException& cax) {
|
||||
error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
|
@ -228,4 +192,3 @@ CoreAudioSource::update_header (jack_nframes_t when, struct tm&, time_t)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue