diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89ac59d --- /dev/null +++ b/.gitignore @@ -0,0 +1,58 @@ +*.mode* +*.pbxuser +build/ +obj/ +*.o +openFrameworks.a +openFrameworksDebug.a +openFrameworksUniversal.a +*.app/ + +CustomAdddons/ + +#rule to avoid non-official addons going into git +#see addons/.gitignore + +#codeblocks files +apps/*/*/*.layout +apps/*/*/*.depend +apps/*/*/bin/clickToLaunch* +apps/*/*/bin/libs +apps/*/*/obj + +#rule to avoid non-official apps going into git +#see apps/.gitignore +apps + +#codeblocks OF lib files +libs/openFrameworksCompiled/project/*/*.depend +libs/openFrameworksCompiled/project/*/*.layout + +#linux temporary files +*~ + +#eclipse build folders +#Mac OS X +addons/Debug Mac OS X +addons/Release Mac OS X +libs/openFrameworks/Debug Mac OS X +libs/openFrameworks/Release Mac OS X +apps/*/*/Debug Mac OS X +apps/*/*/Release Mac OS X +.DS_Store +*.perspectivev3 +xcuserdata/ + + +#Linux +addons/Debug Linux +addons/Release Linux +libs/openFrameworks/Debug Linux +libs/openFrameworks/Release Linux +apps/*/*/Debug Linux +apps/*/*/Release Linux +apps/*/*/Debug Linux64 +apps/*/*/Release Linux64 + + + diff --git a/example-audioData/Project.xcconfig b/example-audioData/Project.xcconfig new file mode 100644 index 0000000..c10b9e5 --- /dev/null +++ b/example-audioData/Project.xcconfig @@ -0,0 +1,9 @@ +//THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. +//THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED +OF_PATH = ../../.. + +//THIS HAS ALL THE HEADER AND LIBS FOR OF CORE +#include "../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" + +OTHER_LDFLAGS = $(OF_CORE_LIBS) +HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) diff --git a/example-audioData/bin/data/cat.mp4 b/example-audioData/bin/data/cat.mp4 new file mode 100644 index 0000000..8a4399e Binary files /dev/null and b/example-audioData/bin/data/cat.mp4 differ diff --git a/example-audioData/emptyExample.xcodeproj/project.pbxproj b/example-audioData/emptyExample.xcodeproj/project.pbxproj new file mode 100644 index 0000000..f7b0139 --- /dev/null +++ b/example-audioData/emptyExample.xcodeproj/project.pbxproj @@ -0,0 +1,614 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + 644DD81217A21B4D009950CB /* fft.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 644DD80E17A21B4D009950CB /* fft.cpp */; }; + 644DD81317A21B4D009950CB /* fftOctaveAnalyzer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 644DD81017A21B4D009950CB /* fftOctaveAnalyzer.cpp */; }; + BBAB23CB13894F3D00AA2426 /* GLUT.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = BBAB23BE13894E4700AA2426 /* GLUT.framework */; }; + E4328149138ABC9F0047C5CB /* openFrameworksDebug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E4328148138ABC890047C5CB /* openFrameworksDebug.a */; }; + E45BE97B0E8CC7DD009D7055 /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9710E8CC7DD009D7055 /* AGL.framework */; }; + E45BE97C0E8CC7DD009D7055 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9720E8CC7DD009D7055 /* ApplicationServices.framework */; }; + E45BE97D0E8CC7DD009D7055 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9730E8CC7DD009D7055 /* AudioToolbox.framework */; }; + E45BE97E0E8CC7DD009D7055 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9740E8CC7DD009D7055 /* Carbon.framework */; }; + E45BE97F0E8CC7DD009D7055 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9750E8CC7DD009D7055 /* CoreAudio.framework */; }; + E45BE9800E8CC7DD009D7055 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9760E8CC7DD009D7055 /* CoreFoundation.framework */; }; + E45BE9810E8CC7DD009D7055 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9770E8CC7DD009D7055 /* CoreServices.framework */; }; + E45BE9830E8CC7DD009D7055 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9790E8CC7DD009D7055 /* OpenGL.framework */; }; + E45BE9840E8CC7DD009D7055 /* QuickTime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE97A0E8CC7DD009D7055 /* QuickTime.framework */; }; + E4B69E200A3A1BDC003C02F2 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4B69E1D0A3A1BDC003C02F2 /* main.cpp */; }; + E4B69E210A3A1BDC003C02F2 /* testApp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4B69E1E0A3A1BDC003C02F2 /* testApp.cpp */; }; + E4C2424710CC5A17004149E2 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4C2424410CC5A17004149E2 /* AppKit.framework */; }; + E4C2424810CC5A17004149E2 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4C2424510CC5A17004149E2 /* Cocoa.framework */; }; + E4C2424910CC5A17004149E2 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4C2424610CC5A17004149E2 /* IOKit.framework */; }; + E4EB6799138ADC1D00A09F29 /* GLUT.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBAB23BE13894E4700AA2426 /* GLUT.framework */; }; + E7BAFC26176BDFAC0097AC71 /* ofxAVFVideoPlayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = E7BAFC23176BDFAC0097AC71 /* ofxAVFVideoPlayer.mm */; }; + E7BAFC27176BDFAC0097AC71 /* ofxAVFVideoRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = E7BAFC25176BDFAC0097AC71 /* ofxAVFVideoRenderer.m */; }; + E7BAFC29176BDFD10097AC71 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7BAFC28176BDFD10097AC71 /* AVFoundation.framework */; }; + E7BAFC2B176BE0530097AC71 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7BAFC2A176BE0530097AC71 /* CoreMedia.framework */; }; + E7BAFC2D176BE0CC0097AC71 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7BAFC2C176BE0CC0097AC71 /* QuartzCore.framework */; }; + E7E077E515D3B63C0020DFD4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7E077E415D3B63C0020DFD4 /* CoreVideo.framework */; }; + E7E077E815D3B6510020DFD4 /* QTKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7E077E715D3B6510020DFD4 /* QTKit.framework */; }; + E7F985F815E0DEA3003869B5 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7F985F515E0DE99003869B5 /* Accelerate.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + E4328147138ABC890047C5CB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E4B27C1510CBEB8E00536013; + remoteInfo = openFrameworks; + }; + E4EEB9AB138B136A00A80321 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E4B27C1410CBEB8E00536013; + remoteInfo = openFrameworks; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + E4C2427710CC5ABF004149E2 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + BBAB23CB13894F3D00AA2426 /* GLUT.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 644DD80E17A21B4D009950CB /* fft.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fft.cpp; sourceTree = ""; }; + 644DD80F17A21B4D009950CB /* fft.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fft.h; sourceTree = ""; }; + 644DD81017A21B4D009950CB /* fftOctaveAnalyzer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fftOctaveAnalyzer.cpp; sourceTree = ""; }; + 644DD81117A21B4D009950CB /* fftOctaveAnalyzer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fftOctaveAnalyzer.h; sourceTree = ""; }; + 64C8FE6617B3E5D600C27A09 /* WavFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WavFile.h; sourceTree = ""; }; + BBAB23BE13894E4700AA2426 /* GLUT.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLUT.framework; path = ../../../libs/glut/lib/osx/GLUT.framework; sourceTree = ""; }; + E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = openFrameworksLib.xcodeproj; path = ../../../libs/openFrameworksCompiled/project/osx/openFrameworksLib.xcodeproj; sourceTree = SOURCE_ROOT; }; + E45BE9710E8CC7DD009D7055 /* AGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AGL.framework; path = /System/Library/Frameworks/AGL.framework; sourceTree = ""; }; + E45BE9720E8CC7DD009D7055 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = ""; }; + E45BE9730E8CC7DD009D7055 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = ""; }; + E45BE9740E8CC7DD009D7055 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; + E45BE9750E8CC7DD009D7055 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = ""; }; + E45BE9760E8CC7DD009D7055 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; + E45BE9770E8CC7DD009D7055 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = ""; }; + E45BE9790E8CC7DD009D7055 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = ""; }; + E45BE97A0E8CC7DD009D7055 /* QuickTime.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickTime.framework; path = /System/Library/Frameworks/QuickTime.framework; sourceTree = ""; }; + E4B69B5B0A3A1756003C02F2 /* emptyExampleDebug.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = emptyExampleDebug.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E4B69E1D0A3A1BDC003C02F2 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = src/main.cpp; sourceTree = SOURCE_ROOT; }; + E4B69E1E0A3A1BDC003C02F2 /* testApp.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 30; name = testApp.cpp; path = src/testApp.cpp; sourceTree = SOURCE_ROOT; }; + E4B69E1F0A3A1BDC003C02F2 /* testApp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = testApp.h; path = src/testApp.h; sourceTree = SOURCE_ROOT; }; + E4B6FCAD0C3E899E008CF71C /* openFrameworks-Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = "openFrameworks-Info.plist"; sourceTree = ""; }; + E4C2424410CC5A17004149E2 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + E4C2424510CC5A17004149E2 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; + E4C2424610CC5A17004149E2 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; + E4EB691F138AFCF100A09F29 /* CoreOF.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = CoreOF.xcconfig; path = ../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig; sourceTree = SOURCE_ROOT; }; + E4EB6923138AFD0F00A09F29 /* Project.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Project.xcconfig; sourceTree = ""; }; + E7BAFC22176BDFAC0097AC71 /* ofxAVFVideoPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ofxAVFVideoPlayer.h; sourceTree = ""; }; + E7BAFC23176BDFAC0097AC71 /* ofxAVFVideoPlayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ofxAVFVideoPlayer.mm; sourceTree = ""; }; + E7BAFC24176BDFAC0097AC71 /* ofxAVFVideoRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ofxAVFVideoRenderer.h; sourceTree = ""; }; + E7BAFC25176BDFAC0097AC71 /* ofxAVFVideoRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ofxAVFVideoRenderer.m; sourceTree = ""; }; + E7BAFC28176BDFD10097AC71 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + E7BAFC2A176BE0530097AC71 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; + E7BAFC2C176BE0CC0097AC71 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + E7E077E415D3B63C0020DFD4 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = /System/Library/Frameworks/CoreVideo.framework; sourceTree = ""; }; + E7E077E715D3B6510020DFD4 /* QTKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QTKit.framework; path = /System/Library/Frameworks/QTKit.framework; sourceTree = ""; }; + E7F985F515E0DE99003869B5 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = /System/Library/Frameworks/Accelerate.framework; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + E4B69B590A3A1756003C02F2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E7BAFC2D176BE0CC0097AC71 /* QuartzCore.framework in Frameworks */, + E7BAFC2B176BE0530097AC71 /* CoreMedia.framework in Frameworks */, + E7BAFC29176BDFD10097AC71 /* AVFoundation.framework in Frameworks */, + E7F985F815E0DEA3003869B5 /* Accelerate.framework in Frameworks */, + E7E077E815D3B6510020DFD4 /* QTKit.framework in Frameworks */, + E4EB6799138ADC1D00A09F29 /* GLUT.framework in Frameworks */, + E4328149138ABC9F0047C5CB /* openFrameworksDebug.a in Frameworks */, + E45BE97B0E8CC7DD009D7055 /* AGL.framework in Frameworks */, + E45BE97C0E8CC7DD009D7055 /* ApplicationServices.framework in Frameworks */, + E45BE97D0E8CC7DD009D7055 /* AudioToolbox.framework in Frameworks */, + E45BE97E0E8CC7DD009D7055 /* Carbon.framework in Frameworks */, + E45BE97F0E8CC7DD009D7055 /* CoreAudio.framework in Frameworks */, + E45BE9800E8CC7DD009D7055 /* CoreFoundation.framework in Frameworks */, + E45BE9810E8CC7DD009D7055 /* CoreServices.framework in Frameworks */, + E45BE9830E8CC7DD009D7055 /* OpenGL.framework in Frameworks */, + E45BE9840E8CC7DD009D7055 /* QuickTime.framework in Frameworks */, + E4C2424710CC5A17004149E2 /* AppKit.framework in Frameworks */, + E4C2424810CC5A17004149E2 /* Cocoa.framework in Frameworks */, + E4C2424910CC5A17004149E2 /* IOKit.framework in Frameworks */, + E7E077E515D3B63C0020DFD4 /* CoreVideo.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + BB4B014C10F69532006C3DED /* addons */ = { + isa = PBXGroup; + children = ( + E7BAFC21176BDFAC0097AC71 /* src */, + ); + name = addons; + sourceTree = ""; + }; + BBAB23C913894ECA00AA2426 /* system frameworks */ = { + isa = PBXGroup; + children = ( + E7BAFC2C176BE0CC0097AC71 /* QuartzCore.framework */, + E7BAFC2A176BE0530097AC71 /* CoreMedia.framework */, + E7BAFC28176BDFD10097AC71 /* AVFoundation.framework */, + E7F985F515E0DE99003869B5 /* Accelerate.framework */, + E4C2424410CC5A17004149E2 /* AppKit.framework */, + E4C2424510CC5A17004149E2 /* Cocoa.framework */, + E4C2424610CC5A17004149E2 /* IOKit.framework */, + E45BE9710E8CC7DD009D7055 /* AGL.framework */, + E45BE9720E8CC7DD009D7055 /* ApplicationServices.framework */, + E45BE9730E8CC7DD009D7055 /* AudioToolbox.framework */, + E45BE9740E8CC7DD009D7055 /* Carbon.framework */, + E45BE9750E8CC7DD009D7055 /* CoreAudio.framework */, + E45BE9760E8CC7DD009D7055 /* CoreFoundation.framework */, + E45BE9770E8CC7DD009D7055 /* CoreServices.framework */, + E45BE9790E8CC7DD009D7055 /* OpenGL.framework */, + E45BE97A0E8CC7DD009D7055 /* QuickTime.framework */, + E7E077E415D3B63C0020DFD4 /* CoreVideo.framework */, + E7E077E715D3B6510020DFD4 /* QTKit.framework */, + ); + name = "system frameworks"; + sourceTree = ""; + }; + BBAB23CA13894EDB00AA2426 /* 3rd party frameworks */ = { + isa = PBXGroup; + children = ( + BBAB23BE13894E4700AA2426 /* GLUT.framework */, + ); + name = "3rd party frameworks"; + sourceTree = ""; + }; + E4328144138ABC890047C5CB /* Products */ = { + isa = PBXGroup; + children = ( + E4328148138ABC890047C5CB /* openFrameworksDebug.a */, + ); + name = Products; + sourceTree = ""; + }; + E45BE5980E8CC70C009D7055 /* frameworks */ = { + isa = PBXGroup; + children = ( + BBAB23CA13894EDB00AA2426 /* 3rd party frameworks */, + BBAB23C913894ECA00AA2426 /* system frameworks */, + ); + name = frameworks; + sourceTree = ""; + }; + E4B69B4A0A3A1720003C02F2 = { + isa = PBXGroup; + children = ( + E4B6FCAD0C3E899E008CF71C /* openFrameworks-Info.plist */, + E4EB6923138AFD0F00A09F29 /* Project.xcconfig */, + E4B69E1C0A3A1BDC003C02F2 /* src */, + E4EEC9E9138DF44700A80321 /* openFrameworks */, + BB4B014C10F69532006C3DED /* addons */, + E45BE5980E8CC70C009D7055 /* frameworks */, + E4B69B5B0A3A1756003C02F2 /* emptyExampleDebug.app */, + ); + sourceTree = ""; + }; + E4B69E1C0A3A1BDC003C02F2 /* src */ = { + isa = PBXGroup; + children = ( + E4B69E1D0A3A1BDC003C02F2 /* main.cpp */, + E4B69E1F0A3A1BDC003C02F2 /* testApp.h */, + E4B69E1E0A3A1BDC003C02F2 /* testApp.cpp */, + 64C8FE6617B3E5D600C27A09 /* WavFile.h */, + 644DD80E17A21B4D009950CB /* fft.cpp */, + 644DD80F17A21B4D009950CB /* fft.h */, + 644DD81017A21B4D009950CB /* fftOctaveAnalyzer.cpp */, + 644DD81117A21B4D009950CB /* fftOctaveAnalyzer.h */, + ); + path = src; + sourceTree = SOURCE_ROOT; + }; + E4EEC9E9138DF44700A80321 /* openFrameworks */ = { + isa = PBXGroup; + children = ( + E4EB691F138AFCF100A09F29 /* CoreOF.xcconfig */, + E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */, + ); + name = openFrameworks; + sourceTree = ""; + }; + E7BAFC21176BDFAC0097AC71 /* src */ = { + isa = PBXGroup; + children = ( + E7BAFC22176BDFAC0097AC71 /* ofxAVFVideoPlayer.h */, + E7BAFC23176BDFAC0097AC71 /* ofxAVFVideoPlayer.mm */, + E7BAFC24176BDFAC0097AC71 /* ofxAVFVideoRenderer.h */, + E7BAFC25176BDFAC0097AC71 /* ofxAVFVideoRenderer.m */, + ); + name = src; + path = ../src; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + E4B69B5A0A3A1756003C02F2 /* emptyExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = E4B69B5F0A3A1757003C02F2 /* Build configuration list for PBXNativeTarget "emptyExample" */; + buildPhases = ( + E4B69B580A3A1756003C02F2 /* Sources */, + E4B69B590A3A1756003C02F2 /* Frameworks */, + E4B6FFFD0C3F9AB9008CF71C /* ShellScript */, + E4C2427710CC5ABF004149E2 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + E4EEB9AC138B136A00A80321 /* PBXTargetDependency */, + ); + name = emptyExample; + productName = myOFApp; + productReference = E4B69B5B0A3A1756003C02F2 /* emptyExampleDebug.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + E4B69B4C0A3A1720003C02F2 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = E4B69B4D0A3A1720003C02F2 /* Build configuration list for PBXProject "emptyExample" */; + compatibilityVersion = "Xcode 2.4"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = E4B69B4A0A3A1720003C02F2; + productRefGroup = E4B69B4A0A3A1720003C02F2; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = E4328144138ABC890047C5CB /* Products */; + ProjectRef = E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + E4B69B5A0A3A1756003C02F2 /* emptyExample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + E4328148138ABC890047C5CB /* openFrameworksDebug.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = openFrameworksDebug.a; + remoteRef = E4328147138ABC890047C5CB /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXShellScriptBuildPhase section */ + E4B6FFFD0C3F9AB9008CF71C /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "cp -f ../../../libs/fmodex/lib/osx/libfmodex.dylib \"$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/libfmodex.dylib\"; install_name_tool -change ./libfmodex.dylib @executable_path/libfmodex.dylib \"$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME\";"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + E4B69B580A3A1756003C02F2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E4B69E200A3A1BDC003C02F2 /* main.cpp in Sources */, + E4B69E210A3A1BDC003C02F2 /* testApp.cpp in Sources */, + E7BAFC26176BDFAC0097AC71 /* ofxAVFVideoPlayer.mm in Sources */, + E7BAFC27176BDFAC0097AC71 /* ofxAVFVideoRenderer.m in Sources */, + 644DD81217A21B4D009950CB /* fft.cpp in Sources */, + 644DD81317A21B4D009950CB /* fftOctaveAnalyzer.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + E4EEB9AC138B136A00A80321 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = openFrameworks; + targetProxy = E4EEB9AB138B136A00A80321 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + E4B69B4E0A3A1720003C02F2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E4EB6923138AFD0F00A09F29 /* Project.xcconfig */; + buildSettings = { + ARCHS = "$(NATIVE_ARCH)"; + CONFIGURATION_BUILD_DIR = "$(SRCROOT)/bin/"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + GCC_AUTO_VECTORIZATION = YES; + GCC_ENABLE_SSE3_EXTENSIONS = YES; + GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES; + GCC_INLINES_ARE_PRIVATE_EXTERN = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = NO; + GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = NO; + GCC_WARN_UNINITIALIZED_AUTOS = NO; + GCC_WARN_UNUSED_VALUE = NO; + GCC_WARN_UNUSED_VARIABLE = NO; + HEADER_SEARCH_PATHS = ( + "$(OF_CORE_HEADERS)", + src, + ); + OTHER_CPLUSPLUSFLAGS = ( + "-D__MACOSX_CORE__", + "-lpthread", + "-mtune=native", + ); + SDKROOT = macosx; + }; + name = Debug; + }; + E4B69B4F0A3A1720003C02F2 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E4EB6923138AFD0F00A09F29 /* Project.xcconfig */; + buildSettings = { + ARCHS = "$(NATIVE_ARCH)"; + CONFIGURATION_BUILD_DIR = "$(SRCROOT)/bin/"; + COPY_PHASE_STRIP = YES; + DEAD_CODE_STRIPPING = YES; + GCC_AUTO_VECTORIZATION = YES; + GCC_ENABLE_SSE3_EXTENSIONS = YES; + GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES; + GCC_INLINES_ARE_PRIVATE_EXTERN = NO; + GCC_OPTIMIZATION_LEVEL = 3; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_UNROLL_LOOPS = YES; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = NO; + GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = NO; + GCC_WARN_UNINITIALIZED_AUTOS = NO; + GCC_WARN_UNUSED_VALUE = NO; + GCC_WARN_UNUSED_VARIABLE = NO; + HEADER_SEARCH_PATHS = ( + "$(OF_CORE_HEADERS)", + src, + ); + OTHER_CPLUSPLUSFLAGS = ( + "-D__MACOSX_CORE__", + "-lpthread", + "-mtune=native", + ); + SDKROOT = macosx; + }; + name = Release; + }; + E4B69B600A3A1757003C02F2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../libs/glut/lib/osx\""; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = NONE; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h"; + INFOPLIST_FILE = "openFrameworks-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_4)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_5)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_6)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_14)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_15)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_16)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_17)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_18)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_19)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_20)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_21)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_22)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_23)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_24)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_25)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_26)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_27)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_28)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_29)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_30)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_31)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_32)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_33)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_34)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_35)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_36)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_37)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_38)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_39)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_40)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_41)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_42)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_43)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_44)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_45)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_46)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_47)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_48)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_49)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_50)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_51)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_52)", + ); + PREBINDING = NO; + PRODUCT_NAME = "$(TARGET_NAME)Debug"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + E4B69B610A3A1757003C02F2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../libs/glut/lib/osx\""; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = NONE; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h"; + INFOPLIST_FILE = "openFrameworks-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_4)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_5)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_6)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_14)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_15)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_16)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_17)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_18)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_19)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_20)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_21)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_22)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_23)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_24)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_25)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_26)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_27)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_28)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_29)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_30)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_31)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_32)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_33)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_34)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_35)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_36)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_37)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_38)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_39)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_40)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_41)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_42)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_43)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_44)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_45)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_46)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_47)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_48)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_49)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_50)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_51)", + ); + PREBINDING = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + E4B69B4D0A3A1720003C02F2 /* Build configuration list for PBXProject "emptyExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E4B69B4E0A3A1720003C02F2 /* Debug */, + E4B69B4F0A3A1720003C02F2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E4B69B5F0A3A1757003C02F2 /* Build configuration list for PBXNativeTarget "emptyExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E4B69B600A3A1757003C02F2 /* Debug */, + E4B69B610A3A1757003C02F2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = E4B69B4C0A3A1720003C02F2 /* Project object */; +} diff --git a/example-audioData/emptyExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example-audioData/emptyExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..da00dc2 --- /dev/null +++ b/example-audioData/emptyExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/example-audioData/emptyExample.xcodeproj/xcshareddata/xcschemes/emptyExample Debug.xcscheme b/example-audioData/emptyExample.xcodeproj/xcshareddata/xcschemes/emptyExample Debug.xcscheme new file mode 100644 index 0000000..eb6fa64 --- /dev/null +++ b/example-audioData/emptyExample.xcodeproj/xcshareddata/xcschemes/emptyExample Debug.xcscheme @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example-audioData/emptyExample.xcodeproj/xcshareddata/xcschemes/emptyExample Release.xcscheme b/example-audioData/emptyExample.xcodeproj/xcshareddata/xcschemes/emptyExample Release.xcscheme new file mode 100644 index 0000000..b6977ca --- /dev/null +++ b/example-audioData/emptyExample.xcodeproj/xcshareddata/xcschemes/emptyExample Release.xcscheme @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example-audioData/openFrameworks-Info.plist b/example-audioData/openFrameworks-Info.plist new file mode 100644 index 0000000..e5db555 --- /dev/null +++ b/example-audioData/openFrameworks-Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.yourcompany.openFrameworks + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/example-audioData/src/WavFile.h b/example-audioData/src/WavFile.h new file mode 100644 index 0000000..0ebc3e6 --- /dev/null +++ b/example-audioData/src/WavFile.h @@ -0,0 +1,244 @@ +/** + * WavFile.h + * + * Marek Bereza 2010 + * + * Originally stolen from somewhere. + * + * Version 4 + */ +#pragma once + +#include + +#include +#include +#include +#include +using namespace std; + +#ifndef MIN +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#endif + +#define WAVFILE_READ 1 +#define WAVFILE_WRITE 2 + +class WavFile { +private: + + fstream *file; + int length; +public: + + int getLength() { + return length/channels; + } + float *data; + int channels; + int samplerate; + int bitsPerSample; + + int ioMode; + + void setFormat(int _channels, int _samplerate, int _bitsPerSample) { + channels = _channels; + samplerate = _samplerate; + bitsPerSample = _bitsPerSample; + } + + WavFile() { + channels = 1; + samplerate = 44100; + bitsPerSample = 16; + data = NULL; + file = NULL; + length = 0; + ioMode = WAVFILE_READ; + } + + + ~WavFile() { + close(); + unload(); + } + + + bool open(string path, int RW) { + close(); + ioMode = RW; + if(RW==WAVFILE_WRITE) { + + + close(); + file = new fstream(path.c_str(), ios::out | ios::binary); + + writeFormat(); + return true; + } else { + printf("WavFile: WAVFILE_READ not implemented yet!\n"); + return false; + } + } + + + /** + * This interleaves samples for putting into wav files. + * Give it 2-dim float array (input) and a 1-dim float array (output) + * and a number of samples in each channel and it will fill up the output + */ + static void interleaveSamples(float **in, float *out, int length) { + for(int i = 0; i < length; i++) { + out[i*2 + 0] = in[0][i]; + out[i*2 + 1] = in[1][i]; + } + + } + + void writeFormat() { + short myFormat = 1; + + int mySubChunk1Size = 16; + int myByteRate = samplerate * channels * bitsPerSample/8; + short myBlockAlign = channels * bitsPerSample/8; + + int myChunkSize = 36 + length*bitsPerSample/8; + int myDataSize = length*bitsPerSample/8; + // write the wav file per the wav file format + file->seekp (0, ios::beg); + file->write ("RIFF", 4); + file->write ((char*) &myChunkSize, 4); + file->write ("WAVE", 4); + file->write ("fmt ", 4); + file->write ((char*) &mySubChunk1Size, 4); + file->write ((char*) &myFormat, 2); // should be 1 for PCM + file->write ((char*) &channels, 2); // # channels (1 or 2) + file->write ((char*) &samplerate, 4); // 44100 + file->write ((char*) &myByteRate, 4); // + file->write ((char*) &myBlockAlign, 2); + file->write ((char*) &bitsPerSample, 2); //16 + file->write ("data", 4); + file->write ((char*) &myDataSize, 4); + } + + + /** + * Buffer length is nnumber of samples. + */ + bool write(float *samples, int buffLength) { + if(file==NULL) return false; + short buff[buffLength]; + for(int i = 0; i < buffLength; i++) { + buff[i] = round(samples[i]*32760.f); + } + file->write ((char*)buff, buffLength*sizeof(short)); + length += buffLength; + return true; + } + + + + void close() { + if(file!=NULL) { + if(ioMode==WAVFILE_WRITE) { + writeFormat(); + } + file->close(); + file = NULL; + } + } + + +#define WRITE_BUFF_SIZE 256 + // write out the wav file + bool save(string path) { + + if(data==NULL) return false; + + open(path.c_str(), WAVFILE_WRITE); + + short buff[WRITE_BUFF_SIZE]; + int pos = 0; + while(poswrite ((char*)buff, len*bitsPerSample/8); + } + + close(); + return true; + } + + // this gives you data that you have to free yourself + float *getData() { + float *d = data; + data = NULL; + return d; + } + + // length is the length in samples, not frames + // - must give malloced memory + void setData(float *_data, int _length) { + data = _data; + length = _length; + } + + /** + * Reads an entire file into the data member of this class. It dynamically + * allocates the memory, and never bothers to delete it (unless you call this + * method again), so take care. + */ + bool load(string path) { + + if(file!=NULL) close(); + file = new fstream(path.c_str(), ios::in | ios::binary); + short myFormat,myBlockAlign; + int mySubChunk1Size,myByteRate; + int myChunkSize,myDataSize; + short format = 1; + file->seekg(4, ios::beg); + file->read( (char*) &myChunkSize, 4 ); // read the ChunkSize + file->seekg(16, ios::beg); + file->read( (char*) &mySubChunk1Size, 4 ); // read the SubChunk1Size + file->read( (char*) &format, sizeof(short) ); // read the file format. This should be 1 for PCM + file->read( (char*) &channels, sizeof(short) ); // read the # of channels (1 or 2) + file->read( (char*) &samplerate, sizeof(int) ); // read the samplerate + file->read( (char*) &myByteRate, sizeof(int) ); // read the byterate + file->read( (char*) &myBlockAlign, sizeof(short) ); // read the blockalign + file->read( (char*) &bitsPerSample, sizeof(short) ); // read the bitspersample + + file->seekg(40, ios::beg); + file->read( (char*) &length, sizeof(int) ); // read the size of the data + + length /= sizeof(short); + if(bitsPerSample!=16 || length<=0 || format!=1) { + return false; + } + + // read the data chunk + short *rawData = new short[length]; + file->seekg(44, ios::beg); + file->read((char*)rawData, length*sizeof(short)); + file->close(); // close the input file + + unload(); + // bytes to shorts + data = new float[length]; + printf("Allocated data\n"); + for(int i = 0; i < length; i++) { + data[i] = ((float)rawData[i])/32767.f; + } + delete rawData; + + close(); + + return true; // this should probably be something more descriptive + } + void unload() { + if(data!=NULL) free(data); + data = NULL; + } +}; \ No newline at end of file diff --git a/example-audioData/src/fft.cpp b/example-audioData/src/fft.cpp new file mode 100644 index 0000000..ca3217e --- /dev/null +++ b/example-audioData/src/fft.cpp @@ -0,0 +1,489 @@ +/********************************************************************** + + fft.cpp + + + This class is a C++ wrapper for original code + written by Dominic Mazzoni in September 2000 + + This file contains a few FFT routines, including a real-FFT + routine that is almost twice as fast as a normal complex FFT, + and a power spectrum routine which is more convenient when + you know you don't care about phase information. It now also + contains a few basic windowing functions. + + Some of this code was based on a free implementation of an FFT + by Don Cross, available on the web at: + + http://www.intersrv.com/~dcross/fft.html + + The basic algorithm for his code was based on Numerical Recipes + in Fortran. I optimized his code further by reducing array + accesses, caching the bit reversal table, and eliminating + float-to-double conversions, and I added the routines to + calculate a real FFT and a real power spectrum. + + Note: all of these routines use single-precision floats. + I have found that in practice, floats work well until you + get above 8192 samples. If you need to do a larger FFT, + you need to use doubles. + +**********************************************************************/ + +#include "fft.h" +#include +#include +#include + +int **gFFTBitTable = NULL; +const int MaxFastBits = 16; + +int IsPowerOfTwo(int x) +{ + if (x < 2) + return false; + + if (x & (x - 1)) /* Thanks to 'byang' for this cute trick! */ + return false; + + return true; +} + +int NumberOfBitsNeeded(int PowerOfTwo) +{ + int i; + + if (PowerOfTwo < 2) { + fprintf(stderr, "Error: FFT called with size %d\n", PowerOfTwo); + exit(1); + } + + for (i = 0;; i++) + if (PowerOfTwo & (1 << i)) + return i; +} + +int ReverseBits(int index, int NumBits) +{ + int i, rev; + + for (i = rev = 0; i < NumBits; i++) { + rev = (rev << 1) | (index & 1); + index >>= 1; + } + + return rev; +} + +void InitFFT() +{ + gFFTBitTable = new int *[MaxFastBits]; + + int len = 2; + for (int b = 1; b <= MaxFastBits; b++) { + + gFFTBitTable[b - 1] = new int[len]; + + for (int i = 0; i < len; i++) + gFFTBitTable[b - 1][i] = ReverseBits(i, b); + + len <<= 1; + } +} + +inline int FastReverseBits(int i, int NumBits) +{ + if (NumBits <= MaxFastBits) + return gFFTBitTable[NumBits - 1][i]; + else + return ReverseBits(i, NumBits); +} + +/* + * Complex Fast Fourier Transform + */ + +void FFT(int NumSamples, + bool InverseTransform, + float *RealIn, float *ImagIn, float *RealOut, float *ImagOut) +{ + int NumBits; /* Number of bits needed to store indices */ + int i, j, k, n; + int BlockSize, BlockEnd; + + double angle_numerator = 2.0 * M_PI; + float tr, ti; /* temp real, temp imaginary */ + + if (!IsPowerOfTwo(NumSamples)) { + fprintf(stderr, "%d is not a power of two\n", NumSamples); + exit(1); + } + + if (!gFFTBitTable) + InitFFT(); + + if (InverseTransform) + angle_numerator = -angle_numerator; + + NumBits = NumberOfBitsNeeded(NumSamples); + + /* + ** Do simultaneous data copy and bit-reversal ordering into outputs... + */ + + for (i = 0; i < NumSamples; i++) { + j = FastReverseBits(i, NumBits); + RealOut[j] = RealIn[i]; + ImagOut[j] = (ImagIn == NULL) ? 0.0 : ImagIn[i]; + } + + /* + ** Do the FFT itself... + */ + + BlockEnd = 1; + for (BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1) { + + double delta_angle = angle_numerator / (double) BlockSize; + + float sm2 = sin(-2 * delta_angle); + float sm1 = sin(-delta_angle); + float cm2 = cos(-2 * delta_angle); + float cm1 = cos(-delta_angle); + float w = 2 * cm1; + float ar0, ar1, ar2, ai0, ai1, ai2; + + for (i = 0; i < NumSamples; i += BlockSize) { + ar2 = cm2; + ar1 = cm1; + + ai2 = sm2; + ai1 = sm1; + + for (j = i, n = 0; n < BlockEnd; j++, n++) { + ar0 = w * ar1 - ar2; + ar2 = ar1; + ar1 = ar0; + + ai0 = w * ai1 - ai2; + ai2 = ai1; + ai1 = ai0; + + k = j + BlockEnd; + tr = ar0 * RealOut[k] - ai0 * ImagOut[k]; + ti = ar0 * ImagOut[k] + ai0 * RealOut[k]; + + RealOut[k] = RealOut[j] - tr; + ImagOut[k] = ImagOut[j] - ti; + + RealOut[j] += tr; + ImagOut[j] += ti; + } + } + + BlockEnd = BlockSize; + } + + /* + ** Need to normalize if inverse transform... + */ + + if (InverseTransform) { + float denom = (float) NumSamples; + + for (i = 0; i < NumSamples; i++) { + RealOut[i] /= denom; + ImagOut[i] /= denom; + } + } +} + +/* + * Real Fast Fourier Transform + * + * This function was based on the code in Numerical Recipes in C. + * In Num. Rec., the inner loop is based on a single 1-based array + * of interleaved real and imaginary numbers. Because we have two + * separate zero-based arrays, our indices are quite different. + * Here is the correspondence between Num. Rec. indices and our indices: + * + * i1 <-> real[i] + * i2 <-> imag[i] + * i3 <-> real[n/2-i] + * i4 <-> imag[n/2-i] + */ + +void RealFFT(int NumSamples, float *RealIn, float *RealOut, float *ImagOut) +{ + int Half = NumSamples / 2; + int i; + + float theta = M_PI / Half; + + float *tmpReal = new float[Half]; + float *tmpImag = new float[Half]; + + for (i = 0; i < Half; i++) { + tmpReal[i] = RealIn[2 * i]; + tmpImag[i] = RealIn[2 * i + 1]; + } + + FFT(Half, 0, tmpReal, tmpImag, RealOut, ImagOut); + + float wtemp = float (sin(0.5 * theta)); + + float wpr = -2.0 * wtemp * wtemp; + float wpi = float (sin(theta)); + float wr = 1.0 + wpr; + float wi = wpi; + + int i3; + + float h1r, h1i, h2r, h2i; + + for (i = 1; i < Half / 2; i++) { + + i3 = Half - i; + + h1r = 0.5 * (RealOut[i] + RealOut[i3]); + h1i = 0.5 * (ImagOut[i] - ImagOut[i3]); + h2r = 0.5 * (ImagOut[i] + ImagOut[i3]); + h2i = -0.5 * (RealOut[i] - RealOut[i3]); + + RealOut[i] = h1r + wr * h2r - wi * h2i; + ImagOut[i] = h1i + wr * h2i + wi * h2r; + RealOut[i3] = h1r - wr * h2r + wi * h2i; + ImagOut[i3] = -h1i + wr * h2i + wi * h2r; + + wr = (wtemp = wr) * wpr - wi * wpi + wr; + wi = wi * wpr + wtemp * wpi + wi; + } + + RealOut[0] = (h1r = RealOut[0]) + ImagOut[0]; + ImagOut[0] = h1r - ImagOut[0]; + + delete[]tmpReal; + delete[]tmpImag; +} + +/* + * PowerSpectrum + * + * This function computes the same as RealFFT, above, but + * adds the squares of the real and imaginary part of each + * coefficient, extracting the power and throwing away the + * phase. + * + * For speed, it does not call RealFFT, but duplicates some + * of its code. + */ + +void PowerSpectrum(int NumSamples, float *In, float *Out) +{ + int Half = NumSamples / 2; + int i; + + float theta = M_PI / Half; + + float *tmpReal = new float[Half]; + float *tmpImag = new float[Half]; + float *RealOut = new float[Half]; + float *ImagOut = new float[Half]; + + for (i = 0; i < Half; i++) { + tmpReal[i] = In[2 * i]; + tmpImag[i] = In[2 * i + 1]; + } + + FFT(Half, 0, tmpReal, tmpImag, RealOut, ImagOut); + + float wtemp = float (sin(0.5 * theta)); + + float wpr = -2.0 * wtemp * wtemp; + float wpi = float (sin(theta)); + float wr = 1.0 + wpr; + float wi = wpi; + + int i3; + + float h1r, h1i, h2r, h2i, rt, it; + //float total=0; + + for (i = 1; i < Half / 2; i++) { + + i3 = Half - i; + + h1r = 0.5 * (RealOut[i] + RealOut[i3]); + h1i = 0.5 * (ImagOut[i] - ImagOut[i3]); + h2r = 0.5 * (ImagOut[i] + ImagOut[i3]); + h2i = -0.5 * (RealOut[i] - RealOut[i3]); + + rt = h1r + wr * h2r - wi * h2i; //printf("Realout%i = %f",i,rt);total+=fabs(rt); + it = h1i + wr * h2i + wi * h2r; // printf(" Imageout%i = %f\n",i,it); + + Out[i] = rt * rt + it * it; + + rt = h1r - wr * h2r + wi * h2i; + it = -h1i + wr * h2i + wi * h2r; + + Out[i3] = rt * rt + it * it; + + wr = (wtemp = wr) * wpr - wi * wpi + wr; + wi = wi * wpr + wtemp * wpi + wi; + } + //printf("total = %f\n",total); + rt = (h1r = RealOut[0]) + ImagOut[0]; + it = h1r - ImagOut[0]; + Out[0] = rt * rt + it * it; + + rt = RealOut[Half / 2]; + it = ImagOut[Half / 2]; + Out[Half / 2] = rt * rt + it * it; + + delete[]tmpReal; + delete[]tmpImag; + delete[]RealOut; + delete[]ImagOut; +} + +/* + * Windowing Functions + */ + +int NumWindowFuncs() +{ + return 4; +} + +char *WindowFuncName(int whichFunction) +{ + switch (whichFunction) { + default: + case 0: + return "Rectangular"; + case 1: + return "Bartlett"; + case 2: + return "Hamming"; + case 3: + return "Hanning"; + } +} + +void WindowFunc(int whichFunction, int NumSamples, float *in) +{ + int i; + + if (whichFunction == 1) { + // Bartlett (triangular) window + for (i = 0; i < NumSamples / 2; i++) { + in[i] *= (i / (float) (NumSamples / 2)); + in[i + (NumSamples / 2)] *= + (1.0 - (i / (float) (NumSamples / 2))); + } + } + + if (whichFunction == 2) { + // Hamming + for (i = 0; i < NumSamples; i++) + in[i] *= 0.54 - 0.46 * cos(2 * M_PI * i / (NumSamples - 1)); + } + + if (whichFunction == 3) { + // Hanning + for (i = 0; i < NumSamples; i++) + in[i] *= 0.50 - 0.50 * cos(2 * M_PI * i / (NumSamples - 1)); + } +} + +/* constructor */ +fft::fft() { +} + +/* destructor */ +fft::~fft() { + + +} + +/* Calculate the power spectrum */ +void fft::powerSpectrum(int start, int half, float *data, int windowSize,float *magnitude,float *phase, float *power, float *avg_power) { + int i; + int windowFunc = 3; + float total_power = 0.0f; + + /* processing variables*/ + float *in_real = new float[windowSize]; + float *in_img = new float[windowSize]; + float *out_real = new float[windowSize]; + float *out_img = new float[windowSize]; + + for (i = 0; i < windowSize; i++) { + in_real[i] = data[start + i]; + } + + WindowFunc(windowFunc, windowSize, in_real); + RealFFT(windowSize, in_real, out_real, out_img); + + for (i = 0; i < half; i++) { + /* compute power */ + power[i] = out_real[i]*out_real[i] + out_img[i]*out_img[i]; + total_power += power[i]; + /* compute magnitude and phase */ + magnitude[i] = 2.0*sqrt(power[i]); + + if (magnitude[i] < 0.000001){ // less than 0.1 nV + magnitude[i] = 0; // out of range + } else { + magnitude[i] = 20.0*log10(magnitude[i] + 1); // get to to db scale + } + + + phase[i] = atan2(out_img[i],out_real[i]); + } + /* calculate average power */ + *(avg_power) = total_power / (float) half; + + delete[]in_real; + delete[]in_img; + delete[]out_real; + delete[]out_img; +} + + +void fft::inversePowerSpectrum(int start, int half, int windowSize, float *finalOut,float *magnitude,float *phase) { + int i; + int windowFunc = 3; + + /* processing variables*/ + float *in_real = new float[windowSize]; + float *in_img = new float[windowSize]; + float *out_real = new float[windowSize]; + float *out_img = new float[windowSize]; + + /* get real and imag part */ + for (i = 0; i < half; i++) { + in_real[i] = magnitude[i]*cos(phase[i]); + in_img[i] = magnitude[i]*sin(phase[i]); + } + + /* zero negative frequencies */ + for (i = half; i < windowSize; i++) { + in_real[i] = 0.0; + in_img[i] = 0.0; + } + + FFT(windowSize, 1, in_real, in_img, out_real, out_img); // second parameter indicates inverse transform + WindowFunc(windowFunc, windowSize, out_real); + + for (i = 0; i < windowSize; i++) { + finalOut[start + i] += out_real[i]; + } + + delete[]in_real; + delete[]in_img; + delete[]out_real; + delete[]out_img; +} + + diff --git a/example-audioData/src/fft.h b/example-audioData/src/fft.h new file mode 100644 index 0000000..bae5b37 --- /dev/null +++ b/example-audioData/src/fft.h @@ -0,0 +1,33 @@ + +#ifndef _FFT +#define _FFT + +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif + + +class fft { + + public: + + fft(); + ~fft(); + + /* Calculate the power spectrum */ + void powerSpectrum(int start, int half, float *data, int windowSize,float *magnitude,float *phase, float *power, float *avg_power); + /* ... the inverse */ + void inversePowerSpectrum(int start, int half, int windowSize, float *finalOut,float *magnitude,float *phase); + + void processLogXScale(const float * data,unsigned int insize, double fMax, + float * avout, float * pkout, unsigned int outsize, + float f1, float f2); + + + float avout[15]; + float pkout[15]; + +}; + + +#endif diff --git a/example-audioData/src/fftOctaveAnalyzer.cpp b/example-audioData/src/fftOctaveAnalyzer.cpp new file mode 100644 index 0000000..fcb5ac7 --- /dev/null +++ b/example-audioData/src/fftOctaveAnalyzer.cpp @@ -0,0 +1,98 @@ + +#include "FFTOctaveAnalyzer.h" + + +void FFTOctaveAnalyzer::setup(float samplingRate, int nBandsInTheFFT, int nAveragesPerOctave){ + + samplingRate = samplingRate; + nSpectrum = nBandsInTheFFT; + spectrumFrequencySpan = (samplingRate / 2.0f) / (float)(nSpectrum); + nAverages = nBandsInTheFFT; + // fe: 2f for octave bands, sqrt(2) for half-octave bands, cuberoot(2) for third-octave bands, etc + if (nAveragesPerOctave==0) // um, wtf? + nAveragesPerOctave = 1; + nAveragesPerOctave = nAveragesPerOctave; + averageFrequencyIncrement = pow(2.0f, 1.0f/(float)(nAveragesPerOctave)); + // this isn't currently configurable (used once here then no effect), but here's some reasoning: + // 43 is a good value if you want to approximate "computer" octaves: 44100/2/2/2/2/2/2/2/2/2/2 + // 55 is a good value if you'd rather approximate A-440 octaves: 440/2/2/2 + // 65 is a good value if you'd rather approximate "middle-C" octaves: ~262/2/2 + // you could easily double it if you felt the lowest band was just rumble noise (as it probably is) + // but don't go much smaller unless you have a huge fft window size (see below for more why) + // keep in mind, if you change it, that the number of actual bands may change +/-1, and + // for some values, the last averaging band may not be very useful (may extend above nyquist) + firstOctaveFrequency = 55.0f; + // for each spectrum[] bin, calculate the mapping into the appropriate average[] bin. + // this gives us roughly log-sized averaging bins, subject to how "fine" the spectrum bins are. + // with more spectrum bins, you can better map into the averaging bins (especially at low + // frequencies) or use more averaging bins per octave. with an fft window size of 2048, + // sampling rate of 44100, and first octave around 55, that's about enough to do half-octave + // analysis. if you don't have enough spectrum bins to map adequately into averaging bins + // at the requested number per octave then you'll end up with "empty" averaging bins, where + // there is no spectrum available to map into it. (so... if you have "nonreactive" averages, + // either increase fft buffer size, or decrease number of averages per octave, etc) + spe2avg = new int[nSpectrum]; + int avgidx = 0; + float averageFreq = firstOctaveFrequency; // the "top" of the first averaging bin + // we're looking for the "top" of the first spectrum bin, and i'm just sort of + // guessing that this is where it is (or possibly spectrumFrequencySpan/2?) + // ... either way it's probably close enough for these purposes + float spectrumFreq = spectrumFrequencySpan; + for (int speidx=0; speidx < nSpectrum; speidx++) { + while (spectrumFreq > averageFreq) { + avgidx++; + averageFreq *= averageFrequencyIncrement; + } + spe2avg[speidx] = avgidx; + spectrumFreq += spectrumFrequencySpan; + } + nAverages = avgidx; + averages = new float[nAverages]; + peaks = new float[nAverages]; + peakHoldTimes = new int[nAverages]; + peakHoldTime = 0; // arbitrary + peakDecayRate = 0.9f; // arbitrary + linearEQIntercept = 1.0f; // unity -- no eq by default + linearEQSlope = 0.0f; // unity -- no eq by default +} + +void FFTOctaveAnalyzer::calculate(float * fftData){ + + int last_avgidx = 0; // tracks when we've crossed into a new averaging bin, so store current average + float sum = 0.0f; // running total of spectrum data + int count = 0; // count of spectrums accumulated (for averaging) + for (int speidx=0; speidx < nSpectrum; speidx++) { + count++; + sum += fftData[speidx] * (linearEQIntercept + (float)(speidx) * linearEQSlope); + int avgidx = spe2avg[speidx]; + if (avgidx != last_avgidx) { + + for (int j = last_avgidx; j < avgidx; j++){ + averages[j] = sum / (float)(count); + } + count = 0; + sum = 0.0f; + } + last_avgidx = avgidx; + } + // the last average was probably not calculated... + if ((count > 0) && (last_avgidx < nAverages)){ + averages[last_avgidx] = sum / (float)(count); + } + + // update the peaks separately + for (int i=0; i < nAverages; i++) { + if (averages[i] >= peaks[i]) { + // save new peak level, also reset the hold timer + peaks[i] = averages[i]; + peakHoldTimes[i] = peakHoldTime; + } else { + // current average does not exceed peak, so hold or decay the peak + if (peakHoldTimes[i] > 0) { + peakHoldTimes[i]--; + } else { + peaks[i] *= peakDecayRate; + } + } + } +} diff --git a/example-audioData/src/fftOctaveAnalyzer.h b/example-audioData/src/fftOctaveAnalyzer.h new file mode 100644 index 0000000..8fef773 --- /dev/null +++ b/example-audioData/src/fftOctaveAnalyzer.h @@ -0,0 +1,45 @@ + +#ifndef _FFTANALYZER +#define _FFTANALYZER + +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif + + +class FFTOctaveAnalyzer { + +public: + + //FFT fft; // a reference to the FFT instance + + float samplingRate; // sampling rate in Hz (needed to calculate frequency spans) + int nSpectrum; // number of spectrum bins in the fft + int nAverages; // number of averaging bins here + int nAveragesPerOctave; // number of averages per octave as requested by user + float spectrumFrequencySpan; // the "width" of an fft spectrum bin in Hz + float firstOctaveFrequency; // the "top" of the first averaging bin here in Hz + float averageFrequencyIncrement; // the root-of-two multiplier between averaging bin frequencies + float * averages; // the actual averages + float * peaks; // peaks of the averages, aka "maxAverages" in other implementations + int * peakHoldTimes; // how long to hold THIS peak meter? decay if == 0 + int peakHoldTime; // how long do we hold peaks? (in fft frames) + float peakDecayRate; // how quickly the peaks decay: 0f=instantly .. 1f=not at all + int * spe2avg; // the mapping between spectrum[] indices and averages[] indices + // the fft's log equalizer() is no longer of any use (it would be nonsense to log scale + // the spectrum values into log-sized average bins) so here's a quick-and-dirty linear + // equalizer instead: + float linearEQSlope; // the rate of linear eq + float linearEQIntercept; // the base linear scaling used at the first averaging bin + // the formula is: spectrum[i] * (linearEQIntercept + i * linearEQSlope) + // so.. note that clever use of it can also provide a "gain" control of sorts + // (fe: set intercept to 2f and slope to 0f to double gain) + + void setup(float samplingRate, int nBandsInTheFFT, int nAveragesPerOctave); + + void calculate(float * fftData); + +}; + + +#endif diff --git a/example-audioData/src/main.cpp b/example-audioData/src/main.cpp new file mode 100644 index 0000000..109ffd6 --- /dev/null +++ b/example-audioData/src/main.cpp @@ -0,0 +1,11 @@ +#include "ofMain.h" +#include "testApp.h" +#include "ofAppGlutWindow.h" + +//======================================================================== +int main() +{ + ofAppGlutWindow window; + ofSetupOpenGL(&window, 1040, 600, OF_WINDOW); + ofRunApp( new testApp()); +} diff --git a/example-audioData/src/testApp.cpp b/example-audioData/src/testApp.cpp new file mode 100644 index 0000000..930e844 --- /dev/null +++ b/example-audioData/src/testApp.cpp @@ -0,0 +1,214 @@ +#include "testApp.h" + +#include "WavFile.h" + +bool bWavSaved = false; + +//-------------------------------------------------------------- +void testApp::setup() +{ + ofSetVerticalSync(true); + + // explicitly tell it to load audio (default) + videoPlayer.setShouldLoadAudio(true); + +// videoPlayer.loadMovie("Casey_You_need_noise.mov"); +// videoPlayer.loadMovie("fingers.mov"); + videoPlayer.loadMovie("cat.mp4"); + videoPlayer.play(); + + fftAnalyzer[0].setup(44100, BUFFER_SIZE/2, 2); + fftAnalyzer[0].peakHoldTime = 15; // hold longer + fftAnalyzer[0].peakDecayRate = 0.95f; // decay slower + fftAnalyzer[0].linearEQIntercept = 0.9f; // reduced gain at lowest frequency + fftAnalyzer[0].linearEQSlope = 0.01f; // increasing gain at higher frequencies + + fftAnalyzer[1].setup(44100, BUFFER_SIZE/2, 2); + fftAnalyzer[1].peakHoldTime = 15; // hold longer + fftAnalyzer[1].peakDecayRate = 0.95f; // decay slower + fftAnalyzer[1].linearEQIntercept = 0.9f; // reduced gain at lowest frequency + fftAnalyzer[1].linearEQSlope = 0.01f; // increasing gain at higher frequencies + +} + +//-------------------------------------------------------------- +void testApp::update() +{ + videoPlayer.update(); + + if (videoPlayer.isAudioLoaded()) { + if (!bWavSaved) { + float * interleavedBuffer = videoPlayer.getAllAmplitudes(); + numAmplitudesPerChannel = videoPlayer.getNumAmplitudes() / 2; + leftBuffer = new float[numAmplitudesPerChannel]; + rightBuffer = new float[numAmplitudesPerChannel]; + + for (int i = 0; i < numAmplitudesPerChannel; i++) { + leftBuffer[i] = interleavedBuffer[i * 2 + 0]; + rightBuffer[i] = interleavedBuffer[i * 2 + 1]; + } + + // Save out a wav file. + WavFile wav; + wav.setFormat(2, 44100, 16); + wav.open(ofToDataPath("somefile.wav"), WAVFILE_WRITE); + wav.write(videoPlayer.getAllAmplitudes(), videoPlayer.getNumAmplitudes()); + wav.close(); + + cout << "Audio ready" << endl; + bWavSaved = true; + } + + // calculate fft + float avgPower = 0.0f; + + int idx = (int)(videoPlayer.getPosition() * (numAmplitudesPerChannel - 1)); + fft[0].powerSpectrum(idx, BUFFER_SIZE/2, leftBuffer, BUFFER_SIZE, &magnitude[0][0], &phase[0][0], &power[0][0], &avgPower); + fft[1].powerSpectrum(idx, BUFFER_SIZE/2, rightBuffer, BUFFER_SIZE, &magnitude[1][0], &phase[1][0], &power[1][0], &avgPower); + for (int i = 0; i < BUFFER_SIZE/2; i++) { + freq[0][i] = magnitude[0][i]; + freq[1][i] = magnitude[1][i]; + } + + fftAnalyzer[0].calculate(freq[0]); + fftAnalyzer[1].calculate(freq[1]); + } +} + +//-------------------------------------------------------------- +void testApp::draw() +{ + ofSetColor(255); + ofFill(); + + videoPlayer.draw(20, 20); + + if (bWavSaved) { + const float waveformWidth = ofGetWidth() - 40; + const float waveformHeight = 300; + + float top = ofGetHeight() - waveformHeight - 20; + float left = 20; + int slice = numAmplitudesPerChannel / waveformWidth; + + // draw the audio waveform + ofNoFill(); + + ofSetColor(ofColor::red); + ofBeginShape(); + for (int i = 0; i < waveformWidth; i++) { + ofVertex(left + i, top + waveformHeight / 2.f + leftBuffer[i * slice] * waveformHeight / 2.f); + } + ofEndShape(); + + ofSetColor(ofColor::blue); + ofBeginShape(); + for (int i = 0; i < waveformWidth; i++) { + ofVertex(left + i, top + waveformHeight / 2.f + rightBuffer[i * slice] * waveformHeight / 2.f); + } + ofEndShape(); + + // draw a playhead over the waveform + ofSetColor(ofColor::white); + ofLine(left + videoPlayer.getPosition() * waveformWidth, top, left + videoPlayer.getPosition() * waveformWidth, top + waveformHeight); + + // draw current amplitude on the edges + ofFill(); + ofSetColor(ofColor::red); + ofRect(left, top, waveformWidth * ABS(videoPlayer.getAmplitude(0)), 20); + ofSetColor(ofColor::blue); + ofRect(left, top + waveformHeight - 20, waveformWidth * ABS(videoPlayer.getAmplitude(1)), 20); + + // draw a dot at the playhead position for each channel + ofSetColor(ofColor::red); + ofCircle(left + videoPlayer.getPosition() * waveformWidth, top + waveformHeight / 2.f + videoPlayer.getAmplitude(0) * waveformHeight / 2.f, 5); + ofSetColor(ofColor::blue); + ofCircle(left + videoPlayer.getPosition() * waveformWidth, top + waveformHeight / 2.f + videoPlayer.getAmplitude(1) * waveformHeight / 2.f, 5); + + // draw a frame around the whole thing + ofSetColor(ofColor::white); + ofNoFill(); + ofRect(left, top, waveformWidth, waveformHeight); + + // draw fft bands + ofFill(); + + left += 320 + 20; + slice = 320 / fftAnalyzer[0].nAverages; + + ofSetColor(255); + for (int i = 0; i < fftAnalyzer[0].nAverages; i++) { + ofRect(left + (i * slice), 20 + 240, slice, -fftAnalyzer[0].averages[i] * 6); + } + ofSetColor(ofColor::red); + for (int i = 0; i < fftAnalyzer[0].nAverages; i++) { + ofRect(left + (i * slice), 20 + 240 - fftAnalyzer[0].peaks[i] * 6, slice, -4); + } + + left += 320 + 20; + slice = 320 / fftAnalyzer[1].nAverages; + + ofSetColor(255); + for (int i = 0; i < fftAnalyzer[1].nAverages; i++) { + ofRect(left + (i * slice), 20 + 240, slice, -fftAnalyzer[1].averages[i] * 6); + } + ofSetColor(ofColor::blue); + for (int i = 0; i < fftAnalyzer[1].nAverages; i++) { + ofRect(left + (i * slice), 20 + 240 - fftAnalyzer[1].peaks[i] * 6, slice, -4); + } + } +} + +//-------------------------------------------------------------- +void testApp::keyPressed(int key) +{ + +} + +//-------------------------------------------------------------- +void testApp::keyReleased(int key) +{ + +} + +//-------------------------------------------------------------- +void testApp::mouseMoved(int x, int y) +{ + +} + +//-------------------------------------------------------------- +void testApp::mouseDragged(int x, int y, int button) +{ + +} + +//-------------------------------------------------------------- +void testApp::mousePressed(int x, int y, int button) +{ + +} + +//-------------------------------------------------------------- +void testApp::mouseReleased(int x, int y, int button) +{ + +} + +//-------------------------------------------------------------- +void testApp::windowResized(int w, int h) +{ + +} + +//-------------------------------------------------------------- +void testApp::gotMessage(ofMessage msg) +{ + +} + +//-------------------------------------------------------------- +void testApp::dragEvent(ofDragInfo dragInfo) +{ + +} diff --git a/example-audioData/src/testApp.h b/example-audioData/src/testApp.h new file mode 100644 index 0000000..1bcc0be --- /dev/null +++ b/example-audioData/src/testApp.h @@ -0,0 +1,42 @@ +#pragma once + +#include "ofMain.h" +#include "ofxAVFVideoPlayer.h" + +#include "fft.h" +#include "FFTOctaveAnalyzer.h" + +#define BUFFER_SIZE 512 + +//-------------------------------------------------------------- +//-------------------------------------------------------------- +class testApp : public ofBaseApp +{ + public: + void setup(); + void update(); + void draw(); + + void keyPressed (int key); + void keyReleased(int key); + void mouseMoved(int x, int y ); + void mouseDragged(int x, int y, int button); + void mousePressed(int x, int y, int button); + void mouseReleased(int x, int y, int button); + void windowResized(int w, int h); + void dragEvent(ofDragInfo dragInfo); + void gotMessage(ofMessage msg); + + ofxAVFVideoPlayer videoPlayer; + + float * leftBuffer; + float * rightBuffer; + int numAmplitudesPerChannel; + + float magnitude[2][BUFFER_SIZE]; + float phase[2][BUFFER_SIZE]; + float power[2][BUFFER_SIZE]; + float freq[2][BUFFER_SIZE/2]; + fft fft[2]; + FFTOctaveAnalyzer fftAnalyzer[2]; +}; diff --git a/example/Project.xcconfig b/example/Project.xcconfig new file mode 100644 index 0000000..c10b9e5 --- /dev/null +++ b/example/Project.xcconfig @@ -0,0 +1,9 @@ +//THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. +//THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED +OF_PATH = ../../.. + +//THIS HAS ALL THE HEADER AND LIBS FOR OF CORE +#include "../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" + +OTHER_LDFLAGS = $(OF_CORE_LIBS) +HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) diff --git a/example/bin/data/test.mov b/example/bin/data/test.mov new file mode 100644 index 0000000..0867a00 Binary files /dev/null and b/example/bin/data/test.mov differ diff --git a/example/example-player.xcodeproj/project.pbxproj b/example/example-player.xcodeproj/project.pbxproj new file mode 100644 index 0000000..c53f9bf --- /dev/null +++ b/example/example-player.xcodeproj/project.pbxproj @@ -0,0 +1,600 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + BBAB23CB13894F3D00AA2426 /* GLUT.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = BBAB23BE13894E4700AA2426 /* GLUT.framework */; }; + E4328149138ABC9F0047C5CB /* openFrameworksDebug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E4328148138ABC890047C5CB /* openFrameworksDebug.a */; }; + E45BE97B0E8CC7DD009D7055 /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9710E8CC7DD009D7055 /* AGL.framework */; }; + E45BE97C0E8CC7DD009D7055 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9720E8CC7DD009D7055 /* ApplicationServices.framework */; }; + E45BE97D0E8CC7DD009D7055 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9730E8CC7DD009D7055 /* AudioToolbox.framework */; }; + E45BE97E0E8CC7DD009D7055 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9740E8CC7DD009D7055 /* Carbon.framework */; }; + E45BE97F0E8CC7DD009D7055 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9750E8CC7DD009D7055 /* CoreAudio.framework */; }; + E45BE9800E8CC7DD009D7055 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9760E8CC7DD009D7055 /* CoreFoundation.framework */; }; + E45BE9810E8CC7DD009D7055 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9770E8CC7DD009D7055 /* CoreServices.framework */; }; + E45BE9830E8CC7DD009D7055 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE9790E8CC7DD009D7055 /* OpenGL.framework */; }; + E45BE9840E8CC7DD009D7055 /* QuickTime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E45BE97A0E8CC7DD009D7055 /* QuickTime.framework */; }; + E4B69E200A3A1BDC003C02F2 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4B69E1D0A3A1BDC003C02F2 /* main.cpp */; }; + E4B69E210A3A1BDC003C02F2 /* testApp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4B69E1E0A3A1BDC003C02F2 /* testApp.cpp */; }; + E4C2424710CC5A17004149E2 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4C2424410CC5A17004149E2 /* AppKit.framework */; }; + E4C2424810CC5A17004149E2 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4C2424510CC5A17004149E2 /* Cocoa.framework */; }; + E4C2424910CC5A17004149E2 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4C2424610CC5A17004149E2 /* IOKit.framework */; }; + E4EB6799138ADC1D00A09F29 /* GLUT.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBAB23BE13894E4700AA2426 /* GLUT.framework */; }; + E7BAFC26176BDFAC0097AC71 /* ofxAVFVideoPlayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = E7BAFC23176BDFAC0097AC71 /* ofxAVFVideoPlayer.mm */; }; + E7BAFC27176BDFAC0097AC71 /* ofxAVFVideoRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = E7BAFC25176BDFAC0097AC71 /* ofxAVFVideoRenderer.m */; }; + E7BAFC29176BDFD10097AC71 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7BAFC28176BDFD10097AC71 /* AVFoundation.framework */; }; + E7BAFC2B176BE0530097AC71 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7BAFC2A176BE0530097AC71 /* CoreMedia.framework */; }; + E7BAFC2D176BE0CC0097AC71 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7BAFC2C176BE0CC0097AC71 /* QuartzCore.framework */; }; + E7E077E515D3B63C0020DFD4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7E077E415D3B63C0020DFD4 /* CoreVideo.framework */; }; + E7E077E815D3B6510020DFD4 /* QTKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7E077E715D3B6510020DFD4 /* QTKit.framework */; }; + E7F985F815E0DEA3003869B5 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7F985F515E0DE99003869B5 /* Accelerate.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + E4328147138ABC890047C5CB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E4B27C1510CBEB8E00536013; + remoteInfo = openFrameworks; + }; + E4EEB9AB138B136A00A80321 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E4B27C1410CBEB8E00536013; + remoteInfo = openFrameworks; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + E4C2427710CC5ABF004149E2 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + BBAB23CB13894F3D00AA2426 /* GLUT.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + BBAB23BE13894E4700AA2426 /* GLUT.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLUT.framework; path = ../../../libs/glut/lib/osx/GLUT.framework; sourceTree = ""; }; + E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = openFrameworksLib.xcodeproj; path = ../../../libs/openFrameworksCompiled/project/osx/openFrameworksLib.xcodeproj; sourceTree = SOURCE_ROOT; }; + E45BE9710E8CC7DD009D7055 /* AGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AGL.framework; path = /System/Library/Frameworks/AGL.framework; sourceTree = ""; }; + E45BE9720E8CC7DD009D7055 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = ""; }; + E45BE9730E8CC7DD009D7055 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = ""; }; + E45BE9740E8CC7DD009D7055 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; + E45BE9750E8CC7DD009D7055 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = ""; }; + E45BE9760E8CC7DD009D7055 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; + E45BE9770E8CC7DD009D7055 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = ""; }; + E45BE9790E8CC7DD009D7055 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = ""; }; + E45BE97A0E8CC7DD009D7055 /* QuickTime.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickTime.framework; path = /System/Library/Frameworks/QuickTime.framework; sourceTree = ""; }; + E4B69B5B0A3A1756003C02F2 /* example-playerDebug.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "example-playerDebug.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + E4B69E1D0A3A1BDC003C02F2 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = src/main.cpp; sourceTree = SOURCE_ROOT; }; + E4B69E1E0A3A1BDC003C02F2 /* testApp.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 30; name = testApp.cpp; path = src/testApp.cpp; sourceTree = SOURCE_ROOT; }; + E4B69E1F0A3A1BDC003C02F2 /* testApp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = testApp.h; path = src/testApp.h; sourceTree = SOURCE_ROOT; }; + E4B6FCAD0C3E899E008CF71C /* openFrameworks-Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = "openFrameworks-Info.plist"; sourceTree = ""; }; + E4C2424410CC5A17004149E2 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + E4C2424510CC5A17004149E2 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; + E4C2424610CC5A17004149E2 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; + E4EB691F138AFCF100A09F29 /* CoreOF.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = CoreOF.xcconfig; path = ../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig; sourceTree = SOURCE_ROOT; }; + E4EB6923138AFD0F00A09F29 /* Project.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Project.xcconfig; sourceTree = ""; }; + E7BAFC22176BDFAC0097AC71 /* ofxAVFVideoPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ofxAVFVideoPlayer.h; sourceTree = ""; }; + E7BAFC23176BDFAC0097AC71 /* ofxAVFVideoPlayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ofxAVFVideoPlayer.mm; sourceTree = ""; }; + E7BAFC24176BDFAC0097AC71 /* ofxAVFVideoRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ofxAVFVideoRenderer.h; sourceTree = ""; }; + E7BAFC25176BDFAC0097AC71 /* ofxAVFVideoRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ofxAVFVideoRenderer.m; sourceTree = ""; }; + E7BAFC28176BDFD10097AC71 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + E7BAFC2A176BE0530097AC71 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; + E7BAFC2C176BE0CC0097AC71 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + E7E077E415D3B63C0020DFD4 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = /System/Library/Frameworks/CoreVideo.framework; sourceTree = ""; }; + E7E077E715D3B6510020DFD4 /* QTKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QTKit.framework; path = /System/Library/Frameworks/QTKit.framework; sourceTree = ""; }; + E7F985F515E0DE99003869B5 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = /System/Library/Frameworks/Accelerate.framework; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + E4B69B590A3A1756003C02F2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E7BAFC2D176BE0CC0097AC71 /* QuartzCore.framework in Frameworks */, + E7BAFC2B176BE0530097AC71 /* CoreMedia.framework in Frameworks */, + E7BAFC29176BDFD10097AC71 /* AVFoundation.framework in Frameworks */, + E7F985F815E0DEA3003869B5 /* Accelerate.framework in Frameworks */, + E7E077E815D3B6510020DFD4 /* QTKit.framework in Frameworks */, + E4EB6799138ADC1D00A09F29 /* GLUT.framework in Frameworks */, + E4328149138ABC9F0047C5CB /* openFrameworksDebug.a in Frameworks */, + E45BE97B0E8CC7DD009D7055 /* AGL.framework in Frameworks */, + E45BE97C0E8CC7DD009D7055 /* ApplicationServices.framework in Frameworks */, + E45BE97D0E8CC7DD009D7055 /* AudioToolbox.framework in Frameworks */, + E45BE97E0E8CC7DD009D7055 /* Carbon.framework in Frameworks */, + E45BE97F0E8CC7DD009D7055 /* CoreAudio.framework in Frameworks */, + E45BE9800E8CC7DD009D7055 /* CoreFoundation.framework in Frameworks */, + E45BE9810E8CC7DD009D7055 /* CoreServices.framework in Frameworks */, + E45BE9830E8CC7DD009D7055 /* OpenGL.framework in Frameworks */, + E45BE9840E8CC7DD009D7055 /* QuickTime.framework in Frameworks */, + E4C2424710CC5A17004149E2 /* AppKit.framework in Frameworks */, + E4C2424810CC5A17004149E2 /* Cocoa.framework in Frameworks */, + E4C2424910CC5A17004149E2 /* IOKit.framework in Frameworks */, + E7E077E515D3B63C0020DFD4 /* CoreVideo.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + BB4B014C10F69532006C3DED /* addons */ = { + isa = PBXGroup; + children = ( + E7BAFC21176BDFAC0097AC71 /* src */, + ); + name = addons; + sourceTree = ""; + }; + BBAB23C913894ECA00AA2426 /* system frameworks */ = { + isa = PBXGroup; + children = ( + E7BAFC2C176BE0CC0097AC71 /* QuartzCore.framework */, + E7BAFC2A176BE0530097AC71 /* CoreMedia.framework */, + E7BAFC28176BDFD10097AC71 /* AVFoundation.framework */, + E7F985F515E0DE99003869B5 /* Accelerate.framework */, + E4C2424410CC5A17004149E2 /* AppKit.framework */, + E4C2424510CC5A17004149E2 /* Cocoa.framework */, + E4C2424610CC5A17004149E2 /* IOKit.framework */, + E45BE9710E8CC7DD009D7055 /* AGL.framework */, + E45BE9720E8CC7DD009D7055 /* ApplicationServices.framework */, + E45BE9730E8CC7DD009D7055 /* AudioToolbox.framework */, + E45BE9740E8CC7DD009D7055 /* Carbon.framework */, + E45BE9750E8CC7DD009D7055 /* CoreAudio.framework */, + E45BE9760E8CC7DD009D7055 /* CoreFoundation.framework */, + E45BE9770E8CC7DD009D7055 /* CoreServices.framework */, + E45BE9790E8CC7DD009D7055 /* OpenGL.framework */, + E45BE97A0E8CC7DD009D7055 /* QuickTime.framework */, + E7E077E415D3B63C0020DFD4 /* CoreVideo.framework */, + E7E077E715D3B6510020DFD4 /* QTKit.framework */, + ); + name = "system frameworks"; + sourceTree = ""; + }; + BBAB23CA13894EDB00AA2426 /* 3rd party frameworks */ = { + isa = PBXGroup; + children = ( + BBAB23BE13894E4700AA2426 /* GLUT.framework */, + ); + name = "3rd party frameworks"; + sourceTree = ""; + }; + E4328144138ABC890047C5CB /* Products */ = { + isa = PBXGroup; + children = ( + E4328148138ABC890047C5CB /* openFrameworksDebug.a */, + ); + name = Products; + sourceTree = ""; + }; + E45BE5980E8CC70C009D7055 /* frameworks */ = { + isa = PBXGroup; + children = ( + BBAB23CA13894EDB00AA2426 /* 3rd party frameworks */, + BBAB23C913894ECA00AA2426 /* system frameworks */, + ); + name = frameworks; + sourceTree = ""; + }; + E4B69B4A0A3A1720003C02F2 = { + isa = PBXGroup; + children = ( + E4B6FCAD0C3E899E008CF71C /* openFrameworks-Info.plist */, + E4EB6923138AFD0F00A09F29 /* Project.xcconfig */, + E4B69E1C0A3A1BDC003C02F2 /* src */, + E4EEC9E9138DF44700A80321 /* openFrameworks */, + BB4B014C10F69532006C3DED /* addons */, + E45BE5980E8CC70C009D7055 /* frameworks */, + E4B69B5B0A3A1756003C02F2 /* example-playerDebug.app */, + ); + sourceTree = ""; + }; + E4B69E1C0A3A1BDC003C02F2 /* src */ = { + isa = PBXGroup; + children = ( + E4B69E1D0A3A1BDC003C02F2 /* main.cpp */, + E4B69E1F0A3A1BDC003C02F2 /* testApp.h */, + E4B69E1E0A3A1BDC003C02F2 /* testApp.cpp */, + ); + path = src; + sourceTree = SOURCE_ROOT; + }; + E4EEC9E9138DF44700A80321 /* openFrameworks */ = { + isa = PBXGroup; + children = ( + E4EB691F138AFCF100A09F29 /* CoreOF.xcconfig */, + E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */, + ); + name = openFrameworks; + sourceTree = ""; + }; + E7BAFC21176BDFAC0097AC71 /* src */ = { + isa = PBXGroup; + children = ( + E7BAFC22176BDFAC0097AC71 /* ofxAVFVideoPlayer.h */, + E7BAFC23176BDFAC0097AC71 /* ofxAVFVideoPlayer.mm */, + E7BAFC24176BDFAC0097AC71 /* ofxAVFVideoRenderer.h */, + E7BAFC25176BDFAC0097AC71 /* ofxAVFVideoRenderer.m */, + ); + name = src; + path = ../src; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + E4B69B5A0A3A1756003C02F2 /* example-player */ = { + isa = PBXNativeTarget; + buildConfigurationList = E4B69B5F0A3A1757003C02F2 /* Build configuration list for PBXNativeTarget "example-player" */; + buildPhases = ( + E4B69B580A3A1756003C02F2 /* Sources */, + E4B69B590A3A1756003C02F2 /* Frameworks */, + E4B6FFFD0C3F9AB9008CF71C /* ShellScript */, + E4C2427710CC5ABF004149E2 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + E4EEB9AC138B136A00A80321 /* PBXTargetDependency */, + ); + name = "example-player"; + productName = myOFApp; + productReference = E4B69B5B0A3A1756003C02F2 /* example-playerDebug.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + E4B69B4C0A3A1720003C02F2 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = E4B69B4D0A3A1720003C02F2 /* Build configuration list for PBXProject "example-player" */; + compatibilityVersion = "Xcode 2.4"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = E4B69B4A0A3A1720003C02F2; + productRefGroup = E4B69B4A0A3A1720003C02F2; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = E4328144138ABC890047C5CB /* Products */; + ProjectRef = E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + E4B69B5A0A3A1756003C02F2 /* example-player */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + E4328148138ABC890047C5CB /* openFrameworksDebug.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = openFrameworksDebug.a; + remoteRef = E4328147138ABC890047C5CB /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXShellScriptBuildPhase section */ + E4B6FFFD0C3F9AB9008CF71C /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "cp -f ../../../libs/fmodex/lib/osx/libfmodex.dylib \"$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/libfmodex.dylib\"; install_name_tool -change ./libfmodex.dylib @executable_path/libfmodex.dylib \"$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME\";"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + E4B69B580A3A1756003C02F2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E4B69E200A3A1BDC003C02F2 /* main.cpp in Sources */, + E4B69E210A3A1BDC003C02F2 /* testApp.cpp in Sources */, + E7BAFC26176BDFAC0097AC71 /* ofxAVFVideoPlayer.mm in Sources */, + E7BAFC27176BDFAC0097AC71 /* ofxAVFVideoRenderer.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + E4EEB9AC138B136A00A80321 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = openFrameworks; + targetProxy = E4EEB9AB138B136A00A80321 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + E4B69B4E0A3A1720003C02F2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E4EB6923138AFD0F00A09F29 /* Project.xcconfig */; + buildSettings = { + ARCHS = "$(NATIVE_ARCH)"; + CONFIGURATION_BUILD_DIR = "$(SRCROOT)/bin/"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + GCC_AUTO_VECTORIZATION = YES; + GCC_ENABLE_SSE3_EXTENSIONS = YES; + GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES; + GCC_INLINES_ARE_PRIVATE_EXTERN = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = NO; + GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = NO; + GCC_WARN_UNINITIALIZED_AUTOS = NO; + GCC_WARN_UNUSED_VALUE = NO; + GCC_WARN_UNUSED_VARIABLE = NO; + HEADER_SEARCH_PATHS = ( + "$(OF_CORE_HEADERS)", + src, + ); + OTHER_CPLUSPLUSFLAGS = ( + "-D__MACOSX_CORE__", + "-lpthread", + "-mtune=native", + ); + SDKROOT = macosx; + }; + name = Debug; + }; + E4B69B4F0A3A1720003C02F2 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E4EB6923138AFD0F00A09F29 /* Project.xcconfig */; + buildSettings = { + ARCHS = "$(NATIVE_ARCH)"; + CONFIGURATION_BUILD_DIR = "$(SRCROOT)/bin/"; + COPY_PHASE_STRIP = YES; + DEAD_CODE_STRIPPING = YES; + GCC_AUTO_VECTORIZATION = YES; + GCC_ENABLE_SSE3_EXTENSIONS = YES; + GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES; + GCC_INLINES_ARE_PRIVATE_EXTERN = NO; + GCC_OPTIMIZATION_LEVEL = 3; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_UNROLL_LOOPS = YES; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = NO; + GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = NO; + GCC_WARN_UNINITIALIZED_AUTOS = NO; + GCC_WARN_UNUSED_VALUE = NO; + GCC_WARN_UNUSED_VARIABLE = NO; + HEADER_SEARCH_PATHS = ( + "$(OF_CORE_HEADERS)", + src, + ); + OTHER_CPLUSPLUSFLAGS = ( + "-D__MACOSX_CORE__", + "-lpthread", + "-mtune=native", + ); + SDKROOT = macosx; + }; + name = Release; + }; + E4B69B600A3A1757003C02F2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../libs/glut/lib/osx\""; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = NONE; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h"; + INFOPLIST_FILE = "openFrameworks-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_4)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_5)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_6)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_14)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_15)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_16)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_17)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_18)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_19)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_20)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_21)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_22)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_23)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_24)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_25)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_26)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_27)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_28)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_29)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_30)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_31)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_32)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_33)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_34)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_35)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_36)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_37)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_38)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_39)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_40)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_41)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_42)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_43)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_44)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_45)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_46)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_47)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_48)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_49)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_50)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_51)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_52)", + ); + PREBINDING = NO; + PRODUCT_NAME = "example-playerDebug"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + E4B69B610A3A1757003C02F2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../libs/glut/lib/osx\""; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = NONE; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h"; + INFOPLIST_FILE = "openFrameworks-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_4)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_5)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_6)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_14)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_15)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_16)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_17)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_18)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_19)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_20)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_21)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_22)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_23)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_24)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_25)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_26)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_27)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_28)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_29)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_30)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_31)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_32)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_33)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_34)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_35)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_36)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_37)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_38)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_39)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_40)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_41)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_42)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_43)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_44)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_45)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_46)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_47)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_48)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_49)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_50)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_51)", + ); + PREBINDING = NO; + PRODUCT_NAME = "example-player"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + E4B69B4D0A3A1720003C02F2 /* Build configuration list for PBXProject "example-player" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E4B69B4E0A3A1720003C02F2 /* Debug */, + E4B69B4F0A3A1720003C02F2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E4B69B5F0A3A1757003C02F2 /* Build configuration list for PBXNativeTarget "example-player" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E4B69B600A3A1757003C02F2 /* Debug */, + E4B69B610A3A1757003C02F2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = E4B69B4C0A3A1720003C02F2 /* Project object */; +} diff --git a/example/example-player.xcodeproj/xcshareddata/xcschemes/emptyExample Debug.xcscheme b/example/example-player.xcodeproj/xcshareddata/xcschemes/emptyExample Debug.xcscheme new file mode 100644 index 0000000..eb6fa64 --- /dev/null +++ b/example/example-player.xcodeproj/xcshareddata/xcschemes/emptyExample Debug.xcscheme @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/example-player.xcodeproj/xcshareddata/xcschemes/emptyExample Release.xcscheme b/example/example-player.xcodeproj/xcshareddata/xcschemes/emptyExample Release.xcscheme new file mode 100644 index 0000000..b6977ca --- /dev/null +++ b/example/example-player.xcodeproj/xcshareddata/xcschemes/emptyExample Release.xcscheme @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/main.cpp b/example/main.cpp deleted file mode 100644 index db10c62..0000000 --- a/example/main.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "ofMain.h" -#include "testApp.h" -#include "ofAppGlutWindow.h" - -//======================================================================== -int main( ){ - - ofAppGlutWindow window; - ofSetupOpenGL(&window, 1920,1080, OF_WINDOW); // <-------- setup the GL context - - // this kicks off the running of my app - // can be OF_WINDOW or OF_FULLSCREEN - // pass in width and height too: - ofRunApp( new testApp()); - -} diff --git a/example/openFrameworks-Info.plist b/example/openFrameworks-Info.plist new file mode 100644 index 0000000..e5db555 --- /dev/null +++ b/example/openFrameworks-Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.yourcompany.openFrameworks + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/example/src/main.cpp b/example/src/main.cpp new file mode 100644 index 0000000..5f56df4 --- /dev/null +++ b/example/src/main.cpp @@ -0,0 +1,11 @@ +#include "ofMain.h" +#include "testApp.h" +#include "ofAppGlutWindow.h" + +//======================================================================== +int main() +{ + ofAppGlutWindow window; + ofSetupOpenGL(&window, 1920, 1080, OF_WINDOW); + ofRunApp(new testApp()); +} diff --git a/example/src/testApp.cpp b/example/src/testApp.cpp new file mode 100644 index 0000000..59bd148 --- /dev/null +++ b/example/src/testApp.cpp @@ -0,0 +1,171 @@ +#include "testApp.h" + +// cleanup +testApp::~testApp() +{ + ofLogNotice() << "cleanup"; + deleteMovie(); +} + +//-------------------------------------------------------------- +void testApp::setup() +{ + ofSetVerticalSync(true); + ofBackground(0); + + videop = NULL; + + // explicitly tell it to load audio (default) + video.setShouldLoadAudio(true); + + video.loadMovie("test.mov"); + video.play(); + video.setLoopState(OF_LOOP_NORMAL); +} + +//-------------------------------------------------------------- +void testApp::update() +{ + video.update(); + if (video.isLoaded() && !image.isAllocated()) { + image.allocate(video.getWidth(), video.getHeight(), OF_IMAGE_COLOR); + } + if (video.isFrameNew()) { + image.setFromPixels(video.getPixelsRef()); + } + + if (videop != NULL) { + videop->update(); + } +} + +//-------------------------------------------------------------- +void testApp::draw() +{ + video.draw(0, 0); + if(image.bAllocated()){ + image.draw(video.getWidth(), 0); + } + + // Draw a timeline at the bottom of the screen. + ofNoFill(); + ofSetColor(255); + ofRect(0, ofGetHeight(), ofGetWidth(), -100); + float playheadX = video.getPosition() * ofGetWidth(); + ofLine(playheadX, ofGetHeight() - 100, playheadX, ofGetHeight()); + ofDrawBitmapStringHighlight(ofToString(video.getCurrentTime()) + " / " + ofToString(video.getDuration()), playheadX + 10, ofGetHeight() - 80); + ofDrawBitmapStringHighlight(ofToString(video.getCurrentFrame()) + " / " + ofToString(video.getTotalNumFrames()), playheadX + 10, ofGetHeight() - 10); + + ofDrawBitmapStringHighlight("Rate: " + ofToString(video.getSpeed(), 2) + "\n" + + "Time: " + ofToString(video.getCurrentTime(), 3) + " / " + ofToString(video.getDuration(), 3) + "\n" + + "Frames: " + ofToString(video.getCurrentFrame()) + " / " + ofToString(video.getTotalNumFrames()) + "\n" + + "Position: " + ofToString(video.getPosition() * 100, 1) + "%" + "\n" + + "Volume: " + ofToString(video.getVolume(), 2) + "\n" + + "\n" + + "[a]/[s]: Play / Stop \n" + + "[space]: Pause \n" + + "[up]/[down]: Adjust Rate \n" + + "[mouse y]: Volume", + 10, 20); +} + +//-------------------------------------------------------------- +void testApp::keyPressed(int key) +{ + switch (key) { + case ' ': + if (video.isPaused()) video.setPaused(false); + else video.setPaused(true); + break; + + case 'a': + video.play(); + break; + + case 's': + video.stop(); + break; + + case OF_KEY_UP: + video.setSpeed(video.getSpeed() * 1.1); + break; + + case OF_KEY_DOWN: + video.setSpeed(video.getSpeed() * 0.9); + break; + + case 'c': + ofLogNotice() << "create a new movie"; + + deleteMovie(); + + //create video + videop = new ofxAVFVideoPlayer; + videop->setShouldLoadAudio(true); + + videop->loadMovie("test.mov"); + + // dont start the movie + // it will get cleaned up anyway +// videop->play(); + break; + + + case 'd': + //destroy video + ofLogNotice() << "destroy the movie"; + deleteMovie(); + + default: + break; + } +} + +//-------------------------------------------------------------- +void testApp::deleteMovie(){ + if (videop != NULL) { + delete videop; + videop = NULL; + } +} + +//-------------------------------------------------------------- +void testApp::keyReleased(int key){ + +} + +//-------------------------------------------------------------- +void testApp::mouseMoved(int x, int y) +{ + video.setVolume(ofMap(y, 0, ofGetHeight(), 1.0, 0.0, true)); +} + +//-------------------------------------------------------------- +void testApp::mouseDragged(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void testApp::mousePressed(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void testApp::mouseReleased(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void testApp::windowResized(int w, int h){ + +} + +//-------------------------------------------------------------- +void testApp::gotMessage(ofMessage msg){ + +} + +//-------------------------------------------------------------- +void testApp::dragEvent(ofDragInfo dragInfo){ + +} diff --git a/example/src/testApp.h b/example/src/testApp.h new file mode 100644 index 0000000..d9d5e47 --- /dev/null +++ b/example/src/testApp.h @@ -0,0 +1,32 @@ +#pragma once + +#include "ofMain.h" +#include "ofxAVFVideoPlayer.h" + +class testApp : public ofBaseApp +{ + public: + + ~testApp(); + + void setup(); + void update(); + void draw(); + + void keyPressed(int key); + void keyReleased(int key); + void mouseMoved(int x, int y); + void mouseDragged(int x, int y, int button); + void mousePressed(int x, int y, int button); + void mouseReleased(int x, int y, int button); + void windowResized(int w, int h); + void dragEvent(ofDragInfo dragInfo); + void gotMessage(ofMessage msg); + + void deleteMovie(); + + ofxAVFVideoPlayer video; + ofImage image; + + ofxAVFVideoPlayer* videop; +}; diff --git a/example/testApp.cpp b/example/testApp.cpp deleted file mode 100644 index 6bc2d06..0000000 --- a/example/testApp.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include "testApp.h" - -//-------------------------------------------------------------- -void testApp::setup(){ - for(int i=0; iloadMovie("EmeliSande_NextToMe.mov"); - } - - - ofSetVerticalSync(true); - -} - -//-------------------------------------------------------------- -void testApp::update(){ - int i=0; - for(auto p : videoPlayers) { - p->update(); - if(true || p->isLoaded()) { - if(ofGetElapsedTimef() > i++ * 0.5) - p->play(); - } - } - - //cout << ofGetFrameRate() << endl; -} - -//-------------------------------------------------------------- -void testApp::draw(){ - int i=0; - for(auto p : videoPlayers) { - p->draw(ofMap(i++, 0, videoPlayers.size(), 0, ofGetWidth()), ofGetHeight()/2 - 108*2, 192*4, 108*4); - } - -} - -//-------------------------------------------------------------- -void testApp::keyPressed(int key){ - switch(key) { - case '1': - videoPlayers[0]->loadMovie("IntroVideo7.mov"); - break; - case '2': - videoPlayers[1]->loadMovie("TheLumineers_1.mov"); - break; - case '3': - videoPlayers[2]->loadMovie("EmeliSande_NextToMe.mov"); - break; - case '4': - videoPlayers[3]->loadMovie("iHRMF2012_SwedishHouseMafia_DontWorryChild.mov"); - break; - } -// videoPlayer2.loadMovie("IntroVideo7.mov"); -} - -//-------------------------------------------------------------- -void testApp::keyReleased(int key){ - -} - -//-------------------------------------------------------------- -void testApp::mouseMoved(int x, int y ){ - -} - -//-------------------------------------------------------------- -void testApp::mouseDragged(int x, int y, int button){ - -} - -//-------------------------------------------------------------- -void testApp::mousePressed(int x, int y, int button){ - -} - -//-------------------------------------------------------------- -void testApp::mouseReleased(int x, int y, int button){ - -} - -//-------------------------------------------------------------- -void testApp::windowResized(int w, int h){ - -} - -//-------------------------------------------------------------- -void testApp::gotMessage(ofMessage msg){ - -} - -//-------------------------------------------------------------- -void testApp::dragEvent(ofDragInfo dragInfo){ - -} \ No newline at end of file diff --git a/example/testApp.h b/example/testApp.h deleted file mode 100644 index a326ba8..0000000 --- a/example/testApp.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "ofMain.h" -#include "ofxAVFVideoPlayer.h" - -class testApp : public ofBaseApp{ - - public: - void setup(); - void update(); - void draw(); - - void keyPressed (int key); - void keyReleased(int key); - void mouseMoved(int x, int y ); - void mouseDragged(int x, int y, int button); - void mousePressed(int x, int y, int button); - void mouseReleased(int x, int y, int button); - void windowResized(int w, int h); - void dragEvent(ofDragInfo dragInfo); - void gotMessage(ofMessage msg); - - std::vector videoPlayers; - static const int N_VIDEO_PLAYERS = 6; - - -}; diff --git a/src/ofxAVFVideoPlayer.h b/src/ofxAVFVideoPlayer.h index a28ada0..305153b 100644 --- a/src/ofxAVFVideoPlayer.h +++ b/src/ofxAVFVideoPlayer.h @@ -14,8 +14,8 @@ #import "ofxAVFVideoRenderer.h" #endif - class ofxAVFVideoPlayer : public ofBaseVideoPlayer { + public: ofxAVFVideoPlayer(); @@ -31,41 +31,57 @@ class ofxAVFVideoPlayer : public ofBaseVideoPlayer { void play(); void stop(); - OF_DEPRECATED_MSG("Use getTexture()->bind() instead. Ensure decodeMode != OF_QTKIT_DECODE_PIXELS_ONLY.", void bind()); - OF_DEPRECATED_MSG("Use getTexture()->unbind() instead. Ensure decodeMode != OF_QTKIT_DECODE_PIXELS_ONLY.", void unbind()); + float getAmplitude(int channel = 0); + float getAmplitudeAt(float pos, int channel = 0); + float * getAllAmplitudes(); + int getNumAmplitudes(); bool isFrameNew(); //returns true if the frame has changed in this update cycle // Returns openFrameworks compatible RGBA pixels. // Be aware of your current render mode. - unsigned char * getPixels(); - ofPixelsRef getPixelsRef(); + unsigned char * getPixels(); + ofPixelsRef getPixelsRef(); // Returns openFrameworks compatible ofTexture pointer. // if decodeMode == OF_QTKIT_DECODE_PIXELS_ONLY, // the returned pointer will be NULL. - ofTexture * getTexture(); - ofTexture& getTextureReference(); + ofTexture * getTexture(); + ofTexture& getTextureReference(); + + bool isLoading(); + bool isLoaded(); + bool shouldLoadAudio(); + void setShouldLoadAudio(bool doLoadAudio); + bool isAudioLoaded(); + bool errorLoading(); + + bool isPlaying(); + bool getIsMovieDone(); float getPosition(); + float getCurrentTime(); float getPositionInSeconds(); - float getSpeed(); - ofLoopType getLoopState(); + int getCurrentFrame(); float getDuration(); - bool getIsMovieDone(); int getTotalNumFrames(); - int getCurrentFrame(); + bool isPaused(); + float getSpeed(); + ofLoopType getLoopState(); + float getVolume(); - void setPaused(bool bPaused); void setPosition(float pct); - void setVolume(float volume); + void setTime(float seconds); + void setPositionInSeconds(float seconds); + void setFrame(int frame); // frame 0 = first frame... void setBalance(float balance); - void setLoopState(ofLoopType state); + void setPaused(bool bPaused); void setSpeed(float speed); - void setFrame(int frame); // frame 0 = first frame... + void setLoopState(ofLoopType state); + void setVolume(float volume); - // ofQTKitPlayer only supports OF_PIXELS_RGB and OF_PIXELS_RGBA. + // ofxAVFVideoPlayer only supports OF_PIXELS_RGB and OF_PIXELS_RGBA. bool setPixelFormat(ofPixelFormat pixelFormat); ofPixelFormat getPixelFormat(); @@ -75,13 +91,6 @@ class ofxAVFVideoPlayer : public ofBaseVideoPlayer { float getWidth(); float getHeight(); - bool isPaused(); - bool isLoaded(); - bool isLoading(); - bool isPlaying(); - bool errorLoading(); - - void firstFrame(); void nextFrame(); void previousFrame(); @@ -90,7 +99,13 @@ class ofxAVFVideoPlayer : public ofBaseVideoPlayer { ofLoopType currentLoopState; + bool bTheFutureIsNow; + bool bPaused; + bool bShouldPlay; + bool bShouldLoadAudio; + + float scrubToTime; bool bNewFrame; bool bHavePixelsChanged; @@ -100,16 +115,13 @@ class ofxAVFVideoPlayer : public ofBaseVideoPlayer { string moviePath; bool bInitialized; + void exit(ofEventArgs& args); - - // updateTexture() pulls texture data from the movie AVFoundation - // renderer into our internal ofTexture. void updateTexture(); void reallocatePixels(); ofFbo fbo; ofTexture tex; - ofPixels pixels; ofPixelFormat pixelFormat; diff --git a/src/ofxAVFVideoPlayer.mm b/src/ofxAVFVideoPlayer.mm index 06da751..e893485 100644 --- a/src/ofxAVFVideoPlayer.mm +++ b/src/ofxAVFVideoPlayer.mm @@ -9,252 +9,577 @@ #include "ofxAVFVideoPlayer.h" #include "Poco/String.h" -ofxAVFVideoPlayer::ofxAVFVideoPlayer() { +//-------------------------------------------------------------- +ofxAVFVideoPlayer::ofxAVFVideoPlayer() +{ moviePlayer = NULL; - bNewFrame = false; + bNewFrame = false; bPaused = true; - duration = 0.0f; + duration = 0.0f; speed = 1.0f; + scrubToTime = 0.0; bInitialized = false; pixelFormat = OF_PIXELS_RGB; currentLoopState = OF_LOOP_NORMAL; + bTheFutureIsNow = false; + bShouldLoadAudio = true; // maybe: change previous default behaviour: explicitly wanting to load audio } -ofxAVFVideoPlayer::~ofxAVFVideoPlayer() { +//-------------------------------------------------------------- +ofxAVFVideoPlayer::~ofxAVFVideoPlayer() +{ close(); } -bool ofxAVFVideoPlayer::loadMovie(string path) { - bInitialized = false; +//-------------------------------------------------------------- +bool ofxAVFVideoPlayer::loadMovie(string path) +{ + + if (bInitialized) { + close(); + } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + moviePlayer = [[AVFVideoRenderer alloc] init]; - bool isURL = false; - - if (Poco::icompare(path.substr(0,7), "http://") == 0 || - Poco::icompare(path.substr(0,8), "https://") == 0 || - Poco::icompare(path.substr(0,7), "rtsp://") == 0) { - isURL = true; + [moviePlayer setUseAlpha:(pixelFormat == OF_PIXELS_RGBA)]; + [moviePlayer setUseTexture:YES]; + [moviePlayer setShouldLoadAudio:bShouldLoadAudio]; + + bTheFutureIsNow = moviePlayer.theFutureIsNow; + + if (Poco::icompare(path.substr(0, 7), "http://") == 0 || + Poco::icompare(path.substr(0, 8), "https://") == 0 || + Poco::icompare(path.substr(0, 7), "rtsp://") == 0) { + [moviePlayer loadURLPath:[NSString stringWithUTF8String:path.c_str()]]; } else { path = ofToDataPath(path, false); + [moviePlayer loadFilePath:[NSString stringWithUTF8String:path.c_str()]]; } - - [moviePlayer loadFile:[NSString stringWithUTF8String:path.c_str()]]; - - [pool release]; + bShouldPlay = false; return true; } -void ofxAVFVideoPlayer::closeMovie() { +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::closeMovie() +{ close(); } -void ofxAVFVideoPlayer::close() { +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::close() +{ pixels.clear(); - if(moviePlayer){ - [moviePlayer release]; - moviePlayer = NULL; + + if (moviePlayer != nil) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + // finalize the movieplayer + // if loading audio and it never got played timeObserver retains moviePlayer + // using a finalizeing solves this + [moviePlayer finalize]; + moviePlayer = nil; + [pool release]; + } + bInitialized = false; + bNewFrame = false; } -void ofxAVFVideoPlayer::idleMovie() { - +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::idleMovie() +{ + update(); } -void ofxAVFVideoPlayer::update() { - if(!moviePlayer) return; - if([moviePlayer isReady]) { - if(!bInitialized) { - // Create the FBO - fbo.allocate([moviePlayer getVideoSize].width, [moviePlayer getVideoSize].height); +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::update() +{ + if (!moviePlayer) return; + + if ([moviePlayer isLoaded]) { + if (!bInitialized) { + if (bTheFutureIsNow) { + reallocatePixels(); + } + else { + fbo.allocate(moviePlayer.width, moviePlayer.height); + } bInitialized = true; - } - - // Render movie into FBO so we can get a texture - fbo.begin(); - [moviePlayer render]; - fbo.end(); + if (scrubToTime != 0.0f) { + setTime(scrubToTime); + scrubToTime = 0.0f; + } + + if (bShouldPlay){ + play(); + bShouldPlay = false; + } + } - bHavePixelsChanged = true; + if (bTheFutureIsNow) { + bNewFrame = [moviePlayer update]; + } + else { + // Render movie into FBO so we can get a texture + fbo.begin(); + [moviePlayer render]; + fbo.end(); + bNewFrame = true; + } + bHavePixelsChanged = bNewFrame; } else { - ofLogNotice("Movie player not ready."); + ofLogNotice("ofxAVFVideoPlayer::update()") << "Movie player not ready"; } } -void ofxAVFVideoPlayer::play() { - [moviePlayer play]; +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::play() +{ + if (bInitialized) { + ofLogVerbose("ofxAVFVideoPlayer::play()") << "Initialized and playing at time " << getCurrentTime(); + [moviePlayer play]; + } + else { + bShouldPlay = true; + } } -void ofxAVFVideoPlayer::stop() { +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::stop() +{ [moviePlayer stop]; } -bool ofxAVFVideoPlayer::isFrameNew() { - return true; +//-------------------------------------------------------------- +bool ofxAVFVideoPlayer::isFrameNew() +{ + return bNewFrame; } -unsigned char* ofxAVFVideoPlayer::getPixels() { - if(!moviePlayer || ![moviePlayer isReady] || !bInitialized) return NULL; - - if(bHavePixelsChanged) { +//-------------------------------------------------------------- +float ofxAVFVideoPlayer::getAmplitude(int channel) +{ + return getAmplitudeAt(getPosition(), channel); +} + +//-------------------------------------------------------------- +float ofxAVFVideoPlayer::getAmplitudeAt(float pos, int channel) +{ + if (bTheFutureIsNow == false) return 0; + + pos = ofClamp(pos, 0, 1); + channel = ofClamp(channel, 0, 1); + + if (!moviePlayer || ![moviePlayer isAudioLoaded] || [moviePlayer numAmplitudes] == 0 || !bInitialized) { + return 0; + } + + int idx = (int)(pos * ([moviePlayer numAmplitudes] - 2)); + + // Make sure the index is pointing at the right channel + // EZ: I know this is ghetto, but it works... + if (idx % 2 == 0 && channel == 1) { + ++idx; + } + else if (idx % 2 == 1 && channel == 0) { + --idx; + } + + float amp; + [moviePlayer.amplitudes getBytes:& range:NSMakeRange(idx * sizeof(float), sizeof(float))]; + return amp; +} + +//-------------------------------------------------------------- +int ofxAVFVideoPlayer::getNumAmplitudes() +{ + return [moviePlayer numAmplitudes]; +} + +//-------------------------------------------------------------- +float * ofxAVFVideoPlayer::getAllAmplitudes() +{ + if (bTheFutureIsNow == false) return NULL; + + return (float *)[moviePlayer.amplitudes bytes]; +} + +//-------------------------------------------------------------- +unsigned char * ofxAVFVideoPlayer::getPixels() +{ + if (bTheFutureIsNow) { + return getPixelsRef().getPixels(); + } + + if (!moviePlayer || ![moviePlayer isLoaded] || !bInitialized) return NULL; + + if (bHavePixelsChanged) { fbo.readToPixels(pixels); bHavePixelsChanged = false; // Don't read pixels until next update() is called } - return pixels.getPixels(); } -ofPixelsRef ofxAVFVideoPlayer::getPixelsRef() { - getPixels(); +//-------------------------------------------------------------- +ofPixelsRef ofxAVFVideoPlayer::getPixelsRef() +{ + if (bTheFutureIsNow) { + if (isLoaded()) { + // Don't get the pixels every frame if it hasn't updated + if (bHavePixelsChanged) { + [moviePlayer pixels:pixels.getPixels()]; + bHavePixelsChanged = false; + } + } + else { + ofLogError("ofxAVFVideoPlayer::getPixelsRef()") << "Returning pixels that may be unallocated. Make sure to initialize the video player before calling getPixelsRef."; + } + } + else { + getPixels(); + } + return pixels; } -ofTexture* ofxAVFVideoPlayer::getTexture() { - if(!moviePlayer || ![moviePlayer isReady] || !bInitialized) return NULL; +//-------------------------------------------------------------- +ofTexture* ofxAVFVideoPlayer::getTexture() +{ + if (bTheFutureIsNow) { + if (moviePlayer.textureAllocated) { + updateTexture(); + return &tex; + } + + return NULL; + } + + if (!moviePlayer || ![moviePlayer isLoaded] || !bInitialized) return NULL; return &fbo.getTextureReference(); } -ofTexture& ofxAVFVideoPlayer::getTextureReference() { - if(!moviePlayer || ![moviePlayer isReady] || !bInitialized) return; +//-------------------------------------------------------------- +ofTexture& ofxAVFVideoPlayer::getTextureReference() +{ + if (bTheFutureIsNow) { + getTexture(); + return tex; + } + + if (!moviePlayer || ![moviePlayer isLoaded] || !bInitialized) return; return fbo.getTextureReference(); } -float ofxAVFVideoPlayer::getPosition() { - // Return a fraction between 0 and 1 representing the position of the playhead - return CMTimeGetSeconds([[moviePlayer player] currentTime]) / CMTimeGetSeconds([moviePlayer getVideoDuration]); +//-------------------------------------------------------------- +bool ofxAVFVideoPlayer::isLoading() +{ + return moviePlayer && [moviePlayer isLoading]; } -float ofxAVFVideoPlayer::getPositionInSeconds() { - return CMTimeGetSeconds([[moviePlayer player] currentTime]); +//-------------------------------------------------------------- +bool ofxAVFVideoPlayer::isLoaded() +{ + return bInitialized; } -float ofxAVFVideoPlayer::getSpeed() { - +//-------------------------------------------------------------- +bool ofxAVFVideoPlayer::shouldLoadAudio() +{ + return bShouldLoadAudio; } -ofLoopType ofxAVFVideoPlayer::getLoopState() { - +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::setShouldLoadAudio(bool doLoadAudio) +{ + bShouldLoadAudio = doLoadAudio; } -float ofxAVFVideoPlayer::getDuration() { - return CMTimeGetSeconds([moviePlayer getVideoDuration]); +//-------------------------------------------------------------- +bool ofxAVFVideoPlayer::isAudioLoaded() +{ + return moviePlayer && [moviePlayer isAudioLoaded]; } -bool ofxAVFVideoPlayer::getIsMovieDone() { +//-------------------------------------------------------------- +bool ofxAVFVideoPlayer::errorLoading() +{ + if (!moviePlayer) return false; + // Error if movie player is not loading and is not ready. + return ![moviePlayer isLoading] && ![moviePlayer isLoaded]; } -int ofxAVFVideoPlayer::getTotalNumFrames() { - +//-------------------------------------------------------------- +bool ofxAVFVideoPlayer::isPlaying() +{ + return moviePlayer && [moviePlayer isPlaying]; } -int ofxAVFVideoPlayer::getCurrentFrame() { - +//-------------------------------------------------------------- +bool ofxAVFVideoPlayer::getIsMovieDone() +{ + return moviePlayer.isMovieDone; } -void ofxAVFVideoPlayer::setPaused(bool bPaused) { - +//-------------------------------------------------------------- +float ofxAVFVideoPlayer::getPosition() +{ + return moviePlayer.position; } -void ofxAVFVideoPlayer::setPosition(float pct) { - [[moviePlayer player] seekToTime:CMTimeMakeWithSeconds(getDuration() * pct, [moviePlayer getVideoDuration].timescale)]; +//-------------------------------------------------------------- +float ofxAVFVideoPlayer::getCurrentTime() +{ + return moviePlayer.currentTime; } -void ofxAVFVideoPlayer::setVolume(float volume) { - +//-------------------------------------------------------------- +float ofxAVFVideoPlayer::getPositionInSeconds() +{ + return getCurrentTime(); } -void ofxAVFVideoPlayer::setBalance(float balance) { - +//-------------------------------------------------------------- +int ofxAVFVideoPlayer::getCurrentFrame() +{ + return moviePlayer.currentFrame; } -void ofxAVFVideoPlayer::setLoopState(ofLoopType state) { - +//-------------------------------------------------------------- +float ofxAVFVideoPlayer::getDuration() +{ + return moviePlayer.duration; } -void ofxAVFVideoPlayer::setSpeed(float speed) { - +//-------------------------------------------------------------- +int ofxAVFVideoPlayer::getTotalNumFrames() +{ + return moviePlayer.totalFrames; } -void ofxAVFVideoPlayer::setFrame(int frame) { +//-------------------------------------------------------------- +bool ofxAVFVideoPlayer::isPaused() +{ + return moviePlayer && [moviePlayer isPaused]; +} + +//-------------------------------------------------------------- +float ofxAVFVideoPlayer::getSpeed() +{ + if (moviePlayer) { + return moviePlayer.playbackRate; + } + return 0; } -bool ofxAVFVideoPlayer::setPixelFormat(ofPixelFormat pixelFormat) { +//-------------------------------------------------------------- +ofLoopType ofxAVFVideoPlayer::getLoopState() +{ + if (moviePlayer && [moviePlayer loops]) + return OF_LOOP_NORMAL; + return OF_LOOP_NONE; } -ofPixelFormat ofxAVFVideoPlayer::getPixelFormat() { +//-------------------------------------------------------------- +float ofxAVFVideoPlayer::getVolume() +{ + if (moviePlayer) { + return moviePlayer.volume; + } + return 0; } -void ofxAVFVideoPlayer::draw(float x, float y, float w, float h) { - if(!bInitialized) return; - fbo.draw(x, y, w, h); +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::setPosition(float pct) +{ + [moviePlayer setPosition:pct]; } -void ofxAVFVideoPlayer::draw(float x, float y) { - if(!bInitialized) return; - fbo.draw(x, y); +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::setTime(float position) +{ + if (![moviePlayer isLoaded]) { + ofLogNotice("ofxAVFVideoPlayer::setCurrentTime()") << "Video player not ready, declaring to scrub to time " << scrubToTime; + scrubToTime = position; + } + else { + [moviePlayer setCurrentTime:position]; + } } -float ofxAVFVideoPlayer::getWidth() { - return [moviePlayer getVideoSize].width; +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::setPositionInSeconds(float seconds) +{ + setTime(seconds); } -float ofxAVFVideoPlayer::getHeight() { - return [moviePlayer getVideoSize].height; +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::setFrame(int frame) +{ + [moviePlayer setCurrentFrame:frame]; } -bool ofxAVFVideoPlayer::isPaused() { - return [moviePlayer player].rate == 0; +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::setVolume(float volume) +{ + [moviePlayer setVolume:volume]; } -bool ofxAVFVideoPlayer::isLoading() { - return [moviePlayer isLoading]; +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::setBalance(float balance) +{ + } -bool ofxAVFVideoPlayer::isLoaded() { - return bInitialized; +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::setPaused(bool bPaused) +{ + [moviePlayer setPaused:bPaused]; } -bool ofxAVFVideoPlayer::errorLoading() { - if(!moviePlayer) return false; +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::setLoopState(ofLoopType state) +{ + if (moviePlayer) { + [moviePlayer setLoops:(state == OF_LOOP_NORMAL)]; + } - // Error if movie player is not loading and is not ready - return (![moviePlayer isLoading] && ![moviePlayer isReady]); + if (state == OF_LOOP_PALINDROME) { + ofLogWarning("ofxAVFVideoPlayer::setLoopState") << "No palindrome yet, sorry!"; + } } -bool ofxAVFVideoPlayer::isPlaying() { +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::setSpeed(float speed) +{ + [moviePlayer setPlaybackRate:speed]; +} + +//-------------------------------------------------------------- +bool ofxAVFVideoPlayer::setPixelFormat(ofPixelFormat newPixelFormat) +{ + if (newPixelFormat != OF_PIXELS_RGB && newPixelFormat != OF_PIXELS_RGBA) { + ofLogWarning("ofxAVFVideoPlayer::setPixelFormat") << "Pixel format " << newPixelFormat << " is not supported."; + return false; + } + if (newPixelFormat != pixelFormat) { + pixelFormat = newPixelFormat; + // If we already have a movie loaded we need to reload + // the movie with the new settings correctly allocated. + if (isLoaded()) { + loadMovie(moviePath); + } + } + return true; } -void ofxAVFVideoPlayer::firstFrame() { +//-------------------------------------------------------------- +ofPixelFormat ofxAVFVideoPlayer::getPixelFormat() +{ + return pixelFormat; +} + +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::draw(float x, float y) +{ + if (!bInitialized) return; + if (bTheFutureIsNow) { + draw(x, y, getWidth(), getHeight()); + } + else { + fbo.draw(x, y); + } } -void ofxAVFVideoPlayer::nextFrame() { +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::draw(float x, float y, float w, float h) +{ + if (!bInitialized) return; + if (bTheFutureIsNow) { + updateTexture(); + tex.draw(x, y, w, h); + } + else { + fbo.draw(x, y, w, h); + } } -void ofxAVFVideoPlayer::previousFrame() { +//-------------------------------------------------------------- +float ofxAVFVideoPlayer::getWidth() +{ + return moviePlayer.width; +} + +//-------------------------------------------------------------- +float ofxAVFVideoPlayer::getHeight() +{ + return moviePlayer.height; +} + +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::firstFrame() +{ + +} + +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::nextFrame() +{ } -void ofxAVFVideoPlayer::updateTexture() { +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::previousFrame() +{ } -void ofxAVFVideoPlayer::reallocatePixels() { +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::updateTexture() +{ + if (bTheFutureIsNow == false) return; -} \ No newline at end of file + if (moviePlayer.textureAllocated) { + tex.setUseExternalTextureID(moviePlayer.textureID); + + ofTextureData& data = tex.getTextureData(); + data.textureTarget = moviePlayer.textureTarget; + data.width = getWidth(); + data.height = getHeight(); + data.tex_w = getWidth(); + data.tex_h = getHeight(); + data.tex_t = getWidth(); + data.tex_u = getHeight(); + } +} + +//-------------------------------------------------------------- +void ofxAVFVideoPlayer::reallocatePixels() +{ + if (bTheFutureIsNow == false) return; + + if (pixelFormat == OF_PIXELS_RGBA) { + pixels.allocate(getWidth(), getHeight(), OF_IMAGE_COLOR_ALPHA); + } + else { + pixels.allocate(getWidth(), getHeight(), OF_IMAGE_COLOR); + } +} diff --git a/src/ofxAVFVideoRenderer.h b/src/ofxAVFVideoRenderer.h index f003a4a..35d8786 100644 --- a/src/ofxAVFVideoRenderer.h +++ b/src/ofxAVFVideoRenderer.h @@ -16,34 +16,100 @@ @interface AVFVideoRenderer : NSObject { - AVPlayer *player; - AVPlayerItem *playerItem; - AVPlayerLayer *playerLayer; + BOOL _bTheFutureIsNow; - CARenderer *layerRenderer; + AVPlayer * _player; + AVPlayerItem * _playerItem; + + // New school video stuff + AVPlayerItemVideoOutput * _playerItemVideoOutput; + CVOpenGLTextureCacheRef _textureCache; + CVOpenGLTextureRef _latestTextureFrame; + CVPixelBufferRef _latestPixelFrame; + + // Old school video stuff + CARenderer * _layerRenderer; + + BOOL _useTexture; + BOOL _useAlpha; + + CGSize _videoSize; + + CMTime _currentTime; + CMTime _duration; + double _frameRate; + double _playbackRate; + BOOL _bLoops; - CGSize videoSize; - CMTime videoDuration; + BOOL _bLoading; + BOOL _bLoaded; + BOOL _bShouldLoadAudio; + BOOL _bAudioLoaded; + BOOL _bPaused; + BOOL _bMovieDone; - BOOL loading; - BOOL ready; - BOOL deallocWhenReady; + // New school audio stuff + NSMutableData *_amplitudes; + int _numAmplitudes; + __block id _periodicTimeObserver; // dont copy that, use it directly in the block + + AVAssetReader* assetReader; + dispatch_queue_t evQ; } - @property (nonatomic, retain) AVPlayer *player; - @property (nonatomic, retain) AVPlayerItem *playerItem; - @property (nonatomic, retain) AVPlayerLayer *playerLayer; - @property (nonatomic, retain) CARenderer *layerRenderer; - -- (void) loadFile:(NSString *)filename; -- (void) play; -- (void) stop; -- (void) playerItemDidReachEnd:(NSNotification *) notification; -//- (void) update; -- (BOOL) isReady; -- (BOOL) isLoading; -- (void) render; - -- (CGSize) getVideoSize; -- (CMTime) getVideoDuration; + +@property (nonatomic, retain) AVPlayer * player; + +@property (nonatomic, assign, readonly, getter = theFutureIsNow) BOOL bTheFutureIsNow; + +@property (nonatomic, assign, readonly) double width; +@property (nonatomic, assign, readonly) double height; + +@property (nonatomic, assign, readonly, getter = isLoading) BOOL bLoading; +@property (nonatomic, assign, readonly, getter = isLoaded) BOOL bLoaded; +@property (nonatomic, assign) BOOL shouldLoadAudio; +@property (nonatomic, assign, readonly, getter = isAudioLoaded) BOOL bAudioLoaded; +@property (nonatomic, assign, getter = isPaused, setter = setPaused:) BOOL bPaused; +@property (nonatomic, assign, readonly, getter = isMovieDone) BOOL bMovieDone; +@property (nonatomic, assign, readonly) BOOL isPlaying; + +@property (nonatomic, assign) BOOL useAlpha; +@property (nonatomic, assign) BOOL useTexture; + +@property (nonatomic, assign, readonly) BOOL textureAllocated; +@property (nonatomic, assign, readonly) GLuint textureID; +@property (nonatomic, assign, readonly) GLenum textureTarget; + +@property (nonatomic, assign, readonly) double frameRate; +@property (nonatomic, assign, readonly) double duration; +@property (nonatomic, assign, readonly) int totalFrames; +@property (nonatomic, assign) double currentTime; +@property (nonatomic, assign) int currentFrame; +@property (nonatomic, assign) double position; +@property (nonatomic, assign) double playbackRate; +@property (nonatomic, assign, getter = loops, setter = setLoops:) BOOL bLoops; +@property (nonatomic, assign) float volume; + +@property (nonatomic, retain, readonly) NSMutableData* amplitudes; +@property (nonatomic, assign, readonly) int numAmplitudes; + +- (void)loadFilePath:(NSString *)filePath; +- (void)loadURLPath:(NSString *)urlPath; +- (void)loadURL:(NSURL *)url; + +- (void)play; +- (void)stop; + +// New school video stuff +- (BOOL)update; +- (void)bindTexture; +- (void)unbindTexture; +- (void)pixels:(unsigned char *)outbuf; + +// Old school video stuff +- (void)render; + +// do some cleanup +- (void)cleanup; +- (void)finalize; @end diff --git a/src/ofxAVFVideoRenderer.m b/src/ofxAVFVideoRenderer.m index bdea6ff..3e27a62 100644 --- a/src/ofxAVFVideoRenderer.m +++ b/src/ofxAVFVideoRenderer.m @@ -7,43 +7,140 @@ // #import "ofxAVFVideoRenderer.h" +#import + +@interface AVFVideoRenderer () + +- (void)playerItemDidReachEnd:(NSNotification *) notification; +- (NSDictionary *)pixelBufferAttributes; +- (void)render; + +@property (nonatomic, retain) AVPlayerItem * playerItem; +@property (nonatomic, retain) AVPlayerItemVideoOutput * playerItemVideoOutput; + +@end @implementation AVFVideoRenderer -@synthesize player, playerItem, playerLayer, layerRenderer; +@synthesize player = _player; +@synthesize playerItem = _playerItem; +@synthesize playerItemVideoOutput = _playerItemVideoOutput; +@synthesize bTheFutureIsNow = _bTheFutureIsNow; -- (void) loadFile:(NSString *)filename { - loading = YES; - ready = NO; - deallocWhenReady = NO; - //NSURL *fileURL = [NSURL URLWithString:filename]; - NSURL *fileURL = [NSURL fileURLWithPath:[filename stringByStandardizingPath]]; - - NSLog(@"Trying to load %@", filename); +@synthesize useTexture = _useTexture; +@synthesize useAlpha = _useAlpha; + +@synthesize bLoading = _bLoading; +@synthesize bLoaded = _bLoaded; +@synthesize shouldLoadAudio = _bShouldLoadAudio; +@synthesize bAudioLoaded = _bAudioLoaded; +@synthesize bPaused = _bPaused; +@synthesize bMovieDone = _bMovieDone; + +@synthesize frameRate = _frameRate; +@synthesize playbackRate = _playbackRate; +@synthesize bLoops = _bLoops; + +@synthesize amplitudes = _amplitudes; +@synthesize numAmplitudes = _numAmplitudes; + +int count = 0; + +//-------------------------------------------------------------- +- (id)init +{ + self = [super init]; + if (self) { + _bTheFutureIsNow = (NSClassFromString(@"AVPlayerItemVideoOutput") != nil); + + if (self.theFutureIsNow) { + self.player = [[AVPlayer alloc] init]; + [self.player autorelease]; + _amplitudes = [[NSMutableData data] retain]; + } + + _bLoading = NO; + _bLoaded = NO; + _bShouldLoadAudio = NO; + _bAudioLoaded = NO; + _bPaused = NO; + _bMovieDone = NO; + + _useTexture = YES; + _useAlpha = NO; + + _frameRate = 0.0; + _playbackRate = 1.0; + _bLoops = false; + } + return self; +} + +//-------------------------------------------------------------- +- (NSDictionary *)pixelBufferAttributes +{ + // kCVPixelFormatType_32ARGB, kCVPixelFormatType_32BGRA, kCVPixelFormatType_422YpCbCr8 + return @{ + (NSString *)kCVPixelBufferOpenGLCompatibilityKey : [NSNumber numberWithBool:self.useTexture], + (NSString *)kCVPixelBufferPixelFormatTypeKey : [NSNumber numberWithInt:kCVPixelFormatType_32ARGB] //[NSNumber numberWithInt:kCVPixelFormatType_422YpCbCr8] + }; +} + +//-------------------------------------------------------------- +- (void)loadFilePath:(NSString *)filePath +{ + [self loadURL:[NSURL fileURLWithPath:[filePath stringByStandardizingPath]]]; +} - AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil]; +//-------------------------------------------------------------- +- (void)loadURLPath:(NSString *)urlPath +{ + [self loadURL:[NSURL URLWithString:urlPath]]; +} + +//-------------------------------------------------------------- +- (void)loadURL:(NSURL *)url +{ + _bLoading = YES; + _bLoaded = NO; + _bAudioLoaded = NO; + _bPaused = NO; + _bMovieDone = NO; + + _frameRate = 0.0; + _playbackRate = 1.0; + +// _useTexture = YES; +// _useAlpha = NO; + + if (_amplitudes) { + [_amplitudes setLength:0]; + } + _numAmplitudes = 0; + + AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil]; NSString *tracksKey = @"tracks"; [asset loadValuesAsynchronouslyForKeys:@[tracksKey] completionHandler: ^{ - static const NSString *ItemStatusContext; + static const NSString *kItemStatusContext; // Perform the following back on the main thread dispatch_async(dispatch_get_main_queue(), ^{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; // Check to see if the file loaded NSError *error; AVKeyValueStatus status = [asset statusOfValueForKey:tracksKey error:&error]; - - if(status == AVKeyValueStatusLoaded) { - // Asset metadata has been loaded. Set up the player + if (status == AVKeyValueStatusLoaded) { + // Asset metadata has been loaded, set up the player. - // Extract the video track to get the video size + // Extract the video track to get the video size and other properties. AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; - videoSize = [videoTrack naturalSize]; - videoDuration = asset.duration; - + _videoSize = [videoTrack naturalSize]; + _currentTime = kCMTimeZero; + _duration = asset.duration; + _frameRate = [videoTrack nominalFrameRate]; + self.playerItem = [AVPlayerItem playerItemWithAsset:asset]; - [self.playerItem addObserver:self forKeyPath:@"status" options:0 context:&ItemStatusContext]; + [self.playerItem addObserver:self forKeyPath:@"status" options:0 context:&kItemStatusContext]; // Notify this object when the player reaches the end // This allows us to loop the video @@ -52,40 +149,250 @@ - (void) loadFile:(NSString *)filename { name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem]; - self.player = [AVPlayer playerWithPlayerItem:self.playerItem]; - - self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:player]; + if (self.theFutureIsNow) { + [self.player replaceCurrentItemWithPlayerItem:self.playerItem]; + + // Create and attach video output. 10.8 Only!!! + self.playerItemVideoOutput = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:[self pixelBufferAttributes]]; + [self.playerItemVideoOutput autorelease]; + + if (self.playerItemVideoOutput) { + [(AVPlayerItemVideoOutput *)self.playerItemVideoOutput setSuppressesPlayerRendering:YES]; + } + [self.player.currentItem addOutput:self.playerItemVideoOutput]; + + // Create CVOpenGLTextureCacheRef for optimal CVPixelBufferRef to GL texture conversion. + if (self.useTexture && !_textureCache) { + CVReturn err = CVOpenGLTextureCacheCreate(kCFAllocatorDefault, NULL, + CGLGetCurrentContext(), CGLGetPixelFormat(CGLGetCurrentContext()), + NULL, &_textureCache); + //(CFDictionaryRef)ctxAttributes, &_textureCache); + if (err != noErr) { + NSLog(@"Error at CVOpenGLTextureCacheCreate %d", err); + } + } + } + else { + self.player = [AVPlayer playerWithPlayerItem:self.playerItem]; + + AVPlayerLayer * playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player]; + _layerRenderer = [CARenderer rendererWithCGLContext:CGLGetCurrentContext() options:nil]; + // need to retain that? + [_layerRenderer retain]; + _layerRenderer.layer = playerLayer; + + // Video is centered on 0,0 for some reason so layer bounds have to start at -width/2,-height/2 + _layerRenderer.bounds = CGRectMake(_videoSize.width * -0.5, _videoSize.height * -0.5, _videoSize.width, _videoSize.height); + playerLayer.bounds = _layerRenderer.bounds; + } - self.layerRenderer = [CARenderer rendererWithCGLContext:CGLGetCurrentContext() options:nil]; - self.layerRenderer.layer = playerLayer; + if (self.shouldLoadAudio && + self.theFutureIsNow) + { + // Only monitor audio if the file is local and has audio tracks. + NSArray *audioTracks = [asset tracksWithMediaType:AVMediaTypeAudio]; + if ([url isFileURL] && [audioTracks count] > 0) { + AVAssetTrack *audioTrack = [audioTracks objectAtIndex:0]; + + NSError *error = nil; + assetReader = [[AVAssetReader alloc] initWithAsset:asset error:&error]; + if (error != nil) { + NSLog(@"Unable to create asset reader %@", [error localizedDescription]); + } + else if (audioTrack != nil) { + // Read the audio track data + NSMutableDictionary *bufferOptions = [NSMutableDictionary dictionary]; + [bufferOptions setObject:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey]; + [bufferOptions setObject:@44100 forKey:AVSampleRateKey]; + [bufferOptions setObject:@2 forKey:AVNumberOfChannelsKey]; + // [bufferOptions setObject:[NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)] forKey:AVChannelLayoutKey]; + [bufferOptions setObject:@32 forKey:AVLinearPCMBitDepthKey]; + [bufferOptions setObject:@NO forKey:AVLinearPCMIsBigEndianKey]; + [bufferOptions setObject:@YES forKey:AVLinearPCMIsFloatKey]; + [bufferOptions setObject:@NO forKey:AVLinearPCMIsNonInterleaved]; + + [assetReader addOutput:[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:audioTrack + outputSettings:bufferOptions]]; + + if (![assetReader startReading]) { + error = [assetReader error]; + NSLog(@"error starting asset reader: %@", [error userInfo]); + } + + count = 0; + + // create dispatch queue + // we need to release this created queue + evQ = dispatch_queue_create("eventQueue", NULL); + + // periodicTimeObserver does retain self (suspecting an issue here...) + // we can ignore this, by not making the block retaining self + // make a reference to self, declare it with __block + // we need to syncronize with this block if we dealloc + __block AVFVideoRenderer* refToSelf = self; + + // Add a periodic time observer that will store the audio track data in a buffer that we can access later + _periodicTimeObserver = [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1001, [audioTrack nominalFrameRate] * 1001) + queue:evQ + usingBlock:^(CMTime time) { + + if ([assetReader status] == AVAssetReaderStatusCompleted) { + // Got all the data we need, kill this block. + [refToSelf.player removeTimeObserver:refToSelf->_periodicTimeObserver]; + _periodicTimeObserver = nil; + + refToSelf->_numAmplitudes = [refToSelf->_amplitudes length] / sizeof(float); + refToSelf->_bAudioLoaded = YES; + + return; + } + + if ([refToSelf->assetReader status] == AVAssetReaderStatusReading) { + AVAssetReaderTrackOutput *output = [[refToSelf->assetReader outputs] objectAtIndex:0]; + CMSampleBufferRef sampleBuffer = [output copyNextSampleBuffer]; + + while (sampleBuffer != NULL) { + + CMBlockBufferRef buffer = CMSampleBufferGetDataBuffer(sampleBuffer); + + if (buffer != NULL) { + + size_t lengthAtOffset; + size_t totalLength; + char* data; + + if (CMBlockBufferGetDataPointer(buffer, 0, &lengthAtOffset, &totalLength, &data) != noErr) { + NSLog(@"error!"); + + // cleanup! + CFRelease(buffer); + CFRelease(sampleBuffer); + + break; + } + + CMItemCount numSamplesInBuffer = CMSampleBufferGetNumSamples(sampleBuffer); + + + AudioBufferList audioBufferList; + + CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer, + NULL, + &audioBufferList, + sizeof(audioBufferList), + NULL, + NULL,kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, // pass in something else + &buffer); + + + + for (int bufferCount = 0; bufferCount < audioBufferList.mNumberBuffers; bufferCount++) { + [refToSelf->_amplitudes appendBytes:audioBufferList.mBuffers[bufferCount].mData + length:audioBufferList.mBuffers[bufferCount].mDataByteSize]; + } + CFRelease(buffer); + } + + + CFRelease(sampleBuffer); + + // get next sampleBuffer + sampleBuffer = [output copyNextSampleBuffer]; + + if (sampleBuffer == NULL) + break; + } + } + }]; + } + } + } - // Video is centered on 0,0 for some reason so layer bounds have to start at -width/2,-height/2 - self.layerRenderer.bounds = CGRectMake(-videoSize.width/2, -videoSize.height/2, videoSize.width, videoSize.height); - self.playerLayer.bounds = self.layerRenderer.bounds; - - ready = YES; - loading = NO; + _bLoading = NO; + _bLoaded = YES; } else { - loading = NO; - ready = NO; - NSLog(@"There was an error loading the file:\n%@", error); + _bLoading = NO; + _bLoaded = NO; + NSLog(@"There was an error loading the file: %@", error); } - - // If dealloc is called immediately after loadFile, we have to defer releasing properties - if(deallocWhenReady) [self dealloc]; - [pool release]; }); }]; } -- (void) dealloc { - if(loading) { - deallocWhenReady = YES; + +//-------------------------------------------------------------- +- (void)finalize +{ + // clenaup + [self cleanup]; + + // release me + [self autorelease]; +} + + +//-------------------------------------------------------------- +- (void)dealloc +{ + // now we are sure this gets deleted + + // safety, if finalize was not called + [self cleanup]; + + [super dealloc]; +} + + +//-------------------------------------------------------------- +- (void)cleanup +{ + [self stop]; + + if (self.theFutureIsNow) { + self.playerItemVideoOutput = nil; + + if (_textureCache != NULL) { + CVOpenGLTextureCacheRelease(_textureCache); + _textureCache = NULL; + } + if (_latestTextureFrame != NULL) { + CVOpenGLTextureRelease(_latestTextureFrame); + _latestTextureFrame = NULL; + } + if (_latestPixelFrame != NULL) { + CVPixelBufferRelease(_latestPixelFrame); + _latestPixelFrame = NULL; + } + + if (_amplitudes) { + [_amplitudes release]; + _amplitudes = nil; + } + _numAmplitudes = 0; + + + // cleanup timeObserver, assetReader, queue + // did we try to load audio? + if (assetReader) { + + // safety in case we never started the player + if (self.player && _periodicTimeObserver) { + [_player removeTimeObserver:_periodicTimeObserver]; + } + + // sync with queue to make sure nobody will use reference to self + dispatch_sync(evQ, ^{}); + + // release the queue + dispatch_release(evQ); + + [assetReader release]; + assetReader = nil; + } + } else { - [self stop]; - // SK: Releasing the CARenderer is slow for some reason // It will freeze the main thread for a few dozen mS. // If you're swapping in and out videos a lot, the loadFile: @@ -93,48 +400,127 @@ - (void) dealloc { // these layers/objects rather than releasing and reallocating // them every time a new file is needed. - if(self.layerRenderer) [self.layerRenderer release]; - - [[NSNotificationCenter defaultCenter] removeObserver:self]; - if(self.playerItem) [self.playerItem removeObserver:self forKeyPath:@"status"]; - - if(self.player) [self.player release]; - if(self.playerItem) [self.playerItem release]; - if(self.playerLayer) [self.playerLayer release]; - if(!deallocWhenReady) [super dealloc]; + if (_layerRenderer) { + [_layerRenderer release]; + _layerRenderer = nil; + } } -} -- (BOOL) isLoading { return loading; } -- (BOOL) isReady { return ready; } + [[NSNotificationCenter defaultCenter] removeObserver:self]; + if (self.playerItem) { + [self.playerItem removeObserver:self forKeyPath:@"status"]; + self.playerItem = nil; + } -- (CGSize) getVideoSize { - return videoSize; + [self.player replaceCurrentItemWithPlayerItem:nil]; + self.player = nil; } -- (CMTime) getVideoDuration { - return videoDuration; -} -- (void) play { + +//-------------------------------------------------------------- +- (void)play +{ [self.player play]; + self.player.rate = _playbackRate; } -- (void) stop { +//-------------------------------------------------------------- +- (void)stop +{ + // Pause and rewind. [self.player pause]; + [self.player seekToTime:kCMTimeZero]; + _bMovieDone = NO; +} + +//-------------------------------------------------------------- +- (void)setPaused:(BOOL)bPaused +{ + _bPaused = bPaused; + if (_bPaused) { + [self.player pause]; + } + else { + [self.player play]; + self.player.rate = _playbackRate; + } } -- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { +//-------------------------------------------------------------- +- (BOOL)isPlaying +{ + if (![self isLoaded]) return NO; + return ![self isMovieDone] && ![self isPaused]; } -- (void) playerItemDidReachEnd:(NSNotification *) notification { - [self.player seekToTime:kCMTimeZero]; - // if(loop) - [self.player play]; +//-------------------------------------------------------------- +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + // Keep this around for now, maybe we'll need it. +} + +//-------------------------------------------------------------- +- (void)playerItemDidReachEnd:(NSNotification *)notification +{ + _bMovieDone = YES; + + if (self.bLoops) { + //start over + _bMovieDone = NO; + [self stop]; + [self play]; + } } -- (void) render { +//-------------------------------------------------------------- +- (BOOL)update +{ + if (self.theFutureIsNow == NO) return YES; + + if (![self isLoaded]) return NO; + + // Check our video output for new frames. + CMTime outputItemTime = [self.playerItemVideoOutput itemTimeForHostTime:CACurrentMediaTime()]; + if ([self.playerItemVideoOutput hasNewPixelBufferForItemTime:outputItemTime]) { + // Get pixels. + if (_latestPixelFrame != NULL) { + CVPixelBufferRelease(_latestPixelFrame); + _latestPixelFrame = NULL; + } + _latestPixelFrame = [self.playerItemVideoOutput copyPixelBufferForItemTime:outputItemTime + itemTimeForDisplay:NULL]; + + if (self.useTexture) { + // Create GL texture. + if (_latestTextureFrame != NULL) { + CVOpenGLTextureRelease(_latestTextureFrame); + _latestTextureFrame = NULL; + CVOpenGLTextureCacheFlush(_textureCache, 0); + } + + CVReturn err = CVOpenGLTextureCacheCreateTextureFromImage(NULL, _textureCache, _latestPixelFrame, NULL, &_latestTextureFrame); + if (err != noErr) { + NSLog(@"Error creating OpenGL texture %d", err); + } + } + + // Update time. + _currentTime = self.player.currentItem.currentTime; + _duration = self.player.currentItem.duration; + + return YES; + } + + return NO; +} + +//-------------------------------------------------------------- +- (void)render +{ + if (self.theFutureIsNow) return; + // From https://qt.gitorious.org/qt/qtmultimedia/blobs/700b4cdf42335ad02ff308cddbfc37b8d49a1e71/src/plugins/avfoundation/mediaplayer/avfvideoframerenderer.mm glPushAttrib(GL_ENABLE_BIT); @@ -142,26 +528,26 @@ - (void) render { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); - - glViewport(0, 0, videoSize.width, videoSize.height); - + + glViewport(0, 0, _videoSize.width, _videoSize.height); + glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); - - glOrtho(0.0f, videoSize.width, videoSize.height, 0.0f, 0.0f, 1.0f); - + + glOrtho(0.0f, _videoSize.width, _videoSize.height, 0.0f, 0.0f, 1.0f); + glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); - - glTranslatef(videoSize.width/2,videoSize.height/2,0); - [layerRenderer beginFrameAtTime:CACurrentMediaTime() timeStamp:NULL]; - [layerRenderer addUpdateRect:layerRenderer.layer.bounds]; - [layerRenderer render]; - [layerRenderer endFrame]; - + glTranslatef(_videoSize.width * 0.5, _videoSize.height * 0.5, 0); + + [_layerRenderer beginFrameAtTime:CACurrentMediaTime() timeStamp:NULL]; + [_layerRenderer addUpdateRect:_layerRenderer.layer.bounds]; + [_layerRenderer render]; + [_layerRenderer endFrame]; + glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); @@ -172,4 +558,197 @@ - (void) render { glFinish(); //Rendering needs to be done before passing texture to video frame } +#pragma mark - Pixels and Texture + +//-------------------------------------------------------------- +- (double)width +{ + return _videoSize.width; +} + +//-------------------------------------------------------------- +- (double)height +{ + return _videoSize.height; +} + +//-------------------------------------------------------------- +- (void)pixels:(unsigned char *)outbuf +{ + if (self.theFutureIsNow == NO) return; + + if (_latestPixelFrame == NULL) return; + +// NSLog(@"pixel buffer width is %ld height %ld and bpr %ld, movie size is %d x %d ", +// CVPixelBufferGetWidth(_latestPixelFrame), +// CVPixelBufferGetHeight(_latestPixelFrame), +// CVPixelBufferGetBytesPerRow(_latestPixelFrame), +// (NSInteger)movieSize.width, (NSInteger)movieSize.height); + if ((NSInteger)self.width != CVPixelBufferGetWidth(_latestPixelFrame) || (NSInteger)self.height != CVPixelBufferGetHeight(_latestPixelFrame)) { + NSLog(@"CoreVideo pixel buffer is %ld x %ld while self reports size of %d x %d. This is most likely caused by a non-square pixel video format such as HDV. Open this video in texture only mode to view it at the appropriate size", + CVPixelBufferGetWidth(_latestPixelFrame), CVPixelBufferGetHeight(_latestPixelFrame), (NSInteger)self.width, (NSInteger)self.height); + return; + } + + if (CVPixelBufferGetPixelFormatType(_latestPixelFrame) != kCVPixelFormatType_32ARGB) { + NSLog(@"ofxAVFVideoRenderer - Frame pixelformat not kCVPixelFormatType_32ARGB: %d, instead %ld", kCVPixelFormatType_32ARGB, CVPixelBufferGetPixelFormatType(_latestPixelFrame)); + return; + } + + CVPixelBufferLockBaseAddress(_latestPixelFrame, kCVPixelBufferLock_ReadOnly); + //If we are using alpha, the ofxAVFVideoPlayer class will have allocated a buffer of size + //video.width * video.height * 4 + //CoreVideo creates alpha video in the format ARGB, and openFrameworks expects RGBA, + //so we need to swap the alpha around using a vImage permutation + vImage_Buffer src = { + CVPixelBufferGetBaseAddress(_latestPixelFrame), + CVPixelBufferGetHeight(_latestPixelFrame), + CVPixelBufferGetWidth(_latestPixelFrame), + CVPixelBufferGetBytesPerRow(_latestPixelFrame) + }; + vImage_Error err; + if (self.useAlpha) { + vImage_Buffer dest = { outbuf, self.height, self.width, self.width * 4 }; + uint8_t permuteMap[4] = { 1, 2, 3, 0 }; //swizzle the alpha around to the end to make ARGB -> RGBA + err = vImagePermuteChannels_ARGB8888(&src, &dest, permuteMap, 0); + } + //If we are are doing RGB then ofxAVFVideoPlayer will have created a buffer of size video.width * video.height * 3 + //so we use vImage to copy them into the out buffer + else { + vImage_Buffer dest = { outbuf, self.height, self.width, self.width * 3 }; + err = vImageConvert_ARGB8888toRGB888(&src, &dest, 0); + } + + CVPixelBufferUnlockBaseAddress(_latestPixelFrame, kCVPixelBufferLock_ReadOnly); + + if (err != kvImageNoError) { + NSLog(@"Error in Pixel Copy vImage_error %ld", err); + } +} + +//-------------------------------------------------------------- +- (BOOL)textureAllocated +{ + if (self.theFutureIsNow == NO) return NO; + + return self.useTexture && _latestTextureFrame != NULL; +} + +//-------------------------------------------------------------- +- (GLuint)textureID +{ + if (self.theFutureIsNow == NO) return -1; + + return CVOpenGLTextureGetName(_latestTextureFrame); +} + +//-------------------------------------------------------------- +- (GLenum)textureTarget +{ + if (self.theFutureIsNow == NO) return 0; + + return CVOpenGLTextureGetTarget(_latestTextureFrame); +} + +//-------------------------------------------------------------- +- (void)bindTexture +{ + if (self.theFutureIsNow == NO) return; + + if (!self.textureAllocated) return; + + GLuint texID = [self textureID]; + GLenum target = [self textureTarget]; + + glEnable(target); + glBindTexture(target, texID); +} + +//-------------------------------------------------------------- +- (void)unbindTexture +{ + if (self.theFutureIsNow == NO) return; + + if (!self.textureAllocated) return; + + GLenum target = [self textureTarget]; + glDisable(target); +} + +#pragma mark - Playhead + +//-------------------------------------------------------------- +- (double)duration +{ + return CMTimeGetSeconds(_duration); +} + +//-------------------------------------------------------------- +- (int)totalFrames +{ + return self.duration * self.frameRate; +} + +//-------------------------------------------------------------- +- (double)currentTime +{ + if (self.theFutureIsNow) { + return CMTimeGetSeconds(_currentTime); + } + + return CMTimeGetSeconds(self.player.currentTime); +} + +//-------------------------------------------------------------- +- (void)setCurrentTime:(double)currentTime +{ + [_player seekToTime:CMTimeMakeWithSeconds(currentTime, _duration.timescale)]; +} + +//-------------------------------------------------------------- +- (int)currentFrame +{ + return self.currentTime * self.frameRate; +} + +//-------------------------------------------------------------- +- (void)setCurrentFrame:(int)currentFrame +{ + float position = currentFrame / (float)self.totalFrames; + [self setPosition:position]; +} + +//-------------------------------------------------------------- +- (double)position +{ + return self.currentTime / self.duration; +} + +//-------------------------------------------------------------- +- (void)setPosition:(double)position +{ + double time = self.duration * position; +// [self.player seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC)]; + [_player seekToTime:CMTimeMakeWithSeconds(time, _duration.timescale)]; +} + +//-------------------------------------------------------------- +- (void)setPlaybackRate:(double)playbackRate +{ + _playbackRate = playbackRate; + [_player setRate:_playbackRate]; +} + +//-------------------------------------------------------------- +- (float)volume +{ + return self.player.volume; +} + +//-------------------------------------------------------------- +- (void)setVolume:(float)volume +{ + self.player.volume = volume; +} + @end