Error cocos3d + Storyboard? - objective-c
I did an Example like CC3DemoMultiScene in iOS objective-c, I follow the same code thing like in example
my AppDelegate follows:
#import "AppDelegate.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{return YES;
}
-(void) applicationWillResignActive: (UIApplication*) application {
[CCDirector.sharedDirector pause];
}
-(void) applicationDidBecomeActive: (UIApplication*) application {
[CCDirector.sharedDirector resume];
}
-(void) applicationDidReceiveMemoryWarning: (UIApplication*) application {
}
-(void) applicationDidEnterBackground: (UIApplication*) application {
[CCDirector.sharedDirector stopAnimation];
}
-(void) applicationWillEnterForeground: (UIApplication*) application {
[CCDirector.sharedDirector startAnimation];
}
-(void)applicationWillTerminate: (UIApplication*) application {
[CC3OpenGL terminateOpenGL];
}
-(void) applicationSignificantTimeChange: (UIApplication*) application {
[CCDirector.sharedDirector setNextDeltaTimeZero: YES];
}
#end
there is not any error meanwhile compile, but when run in iOS Simulator, the App Crashes print me this issues:
2015-08-14 16:43:26.446 ExampleCocos3d[9063:116836] *** Assertion failure in GLint CompileShader(GLenum, const char *)(), /Users/Dennis/Desktop/ExampleCocos3d/Libraries/DennisCocos3D/cocos2d/cocos2d/cocos2d/CCShader.m:173
2015-08-14 16:43:26.462 ExampleCocos3d[9063:116836] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Error compiling shader'
*** First throw call stack:
(
0 CoreFoundation 0x000000010edc6c65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010e642bb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010edc6aca +[NSException raise:format:arguments:] + 106
3 Foundation 0x000000010e149a57 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 169
4 ExampleCocos3d 0x000000010aab3d0c CompileShader + 364
5 ExampleCocos3d 0x000000010aab3964 -[CCShader initWithVertexShaderSource:fragmentShaderSource:] + 212
6 ExampleCocos3d 0x000000010aab3ebd -[CCShader initWithFragmentShaderSource:] + 77
7 ExampleCocos3d 0x000000010aab40d4 +[CCShader initialize] + 180
8 libobjc.A.dylib 0x000000010e6434d6 _class_initialize + 648
9 libobjc.A.dylib 0x000000010e64c6e1 lookUpImpOrForward + 351
10 libobjc.A.dylib 0x000000010e6590d3 objc_msgSend + 211
11 ExampleCocos3d 0x000000010aabd331 -[CCRenderer init] + 353
12 ExampleCocos3d 0x000000010ade7c1b -[CCDirector init] + 875
13 ExampleCocos3d 0x000000010ad6e266 -[CCDirectorIOS init] + 54
14 ExampleCocos3d 0x000000010ade7760 +[CCDirector sharedDirector] + 144
15 ExampleCocos3d 0x000000010ace34bd -[AppDelegate applicationDidBecomeActive:] + 61
16 UIKit 0x000000010c2b92ce -[UIApplication _stopDeactivatingForReason:] + 313
17 UIKit 0x000000010c2ce417 -[UIApplication _handleNonLaunchSpecificActions:forScene:withTransitionContext:] + 2589
18 FrontBoardServices 0x0000000112a845e5 __31-[FBSSerialQueue performAsync:]_block_invoke_2 + 21
19 CoreFoundation 0x000000010ecfa41c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
20 CoreFoundation 0x000000010ecf0165 __CFRunLoopDoBlocks + 341
21 CoreFoundation 0x000000010eceff25 __CFRunLoopRun + 2389
22 CoreFoundation 0x000000010ecef366 CFRunLoopRunSpecific + 470
23 GraphicsServices 0x000000011071ca3e GSEventRunModal + 161
24 UIKit 0x000000010c2be900 UIApplicationMain + 1282
25 Tripsland 0x000000010ad63b4f main + 111
26 libdyld.dylib 0x000000010f465145 start + 1
27 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
//------------------------------------------//
// THANKS GUYS //
// GRETTINGS FROM BOLIVIA //
// ROCK ON!!!! n_n' //
//------------------------------------------//
please help!! or exist any error in the CCShader.m file from Cocos2D Library, the error is generated in:
static GLint
CompileShader(GLenum type, const char *source)
{
GLint shader = glCreateShader(type);
const GLchar *sources[] = {
CCShaderHeader,
CCShaderTypeHeader(type),
source,
};
glShaderSource(shader, 3, sources, NULL);
glCompileShader(shader);
NSCAssert(CCCheckShaderError(shader, GL_COMPILE_STATUS, glGetShaderiv, glGetShaderInfoLog), #"Error compiling shader");
return shader;
}
FIRST EDIT: thanks for the recommendation user2242300
well the .h and .m files from CCShader are in the
cocos2d-library-iOS.xcodeproj/cocos2d/cocos2d/CCShader.h
cocos2d-library-iOS.xcodeproj/cocos2d/cocos2d/CCShader.m
the CCShader.h file have:
#import <Foundation/Foundation.h>
#import "ccTypes.h"
#import "ccMacros.h"
#import "Platforms/CCGL.h"
/// Macro to embed GLSL source
#define CC_GLSL(x) ##x
extern const NSString *CCShaderUniformProjection;
extern const NSString *CCShaderUniformProjectionInv;
extern const NSString *CCShaderUniformViewSize;
extern const NSString *CCShaderUniformViewSizeInPixels;
extern const NSString *CCShaderUniformTime;
extern const NSString *CCShaderUniformSinTime;
extern const NSString *CCShaderUniformCosTime;
extern const NSString *CCShaderUniformRandom01;
extern const NSString *CCShaderUniformMainTexture;
extern const NSString *CCShaderUniformNormalMapTexture;
extern const NSString *CCShaderUniformAlphaTestValue;
#interface CCShader : NSObject<NSCopying>
#property(nonatomic, copy) NSString *debugName;
+(instancetype)shaderNamed:(NSString *)shaderName;
-(instancetype)initWithVertexShaderSource:(NSString *)vertexSource fragmentShaderSource:(NSString *)fragmentSource;
-(instancetype)initWithFragmentShaderSource:(NSString *)source;
+(instancetype)positionColorShader;
+(instancetype)positionTextureColorShader;
+(instancetype)positionTextureColorAlphaTestShader;
+(instancetype)positionTextureA8ColorShader;
#end
and the CCShader.m have:
#import "CCShader_private.h"
#import "ccMacros.h"
#import "Support/CCFileUtils.h"
#import "Support/uthash.h"
#import "CCRenderer_private.h"
#import "CCTexture_private.h"
#import "CCDirector.h"
#import "CCCache.h"
#import "CCGL.h"
enum {
CCAttributePosition,
CCAttributeTexCoord1,
CCAttributeTexCoord2,
CCAttributeColor,
};
const NSString *CCShaderUniformProjection = #"cc_Projection";
const NSString *CCShaderUniformProjectionInv = #"cc_ProjectionInv";
const NSString *CCShaderUniformViewSize = #"cc_ViewSize";
const NSString *CCShaderUniformViewSizeInPixels = #"cc_ViewSizeInPixels";
const NSString *CCShaderUniformTime = #"cc_Time";
const NSString *CCShaderUniformSinTime = #"cc_SinTime";
const NSString *CCShaderUniformCosTime = #"cc_CosTime";
const NSString *CCShaderUniformRandom01 = #"cc_Random01";
const NSString *CCShaderUniformMainTexture = #"cc_MainTexture";
const NSString *CCShaderUniformNormalMapTexture = #"cc_NormalMapTexture";
const NSString *CCShaderUniformAlphaTestValue = #"cc_AlphaTestValue";
// Stringify macros
#define STR(s) #s
#define XSTR(s) STR(s)
/*
main texture size points/pixels?
*/
static const GLchar *CCShaderHeader =
"#ifndef GL_ES\n"
"#define lowp\n"
"#define mediump\n"
"#define highp\n"
"#endif\n\n"
"uniform highp mat4 cc_Projection;\n"
"uniform highp mat4 cc_ProjectionInv;\n"
"uniform highp vec2 cc_ViewSize;\n"
"uniform highp vec2 cc_ViewSizeInPixels;\n"
"uniform highp vec4 cc_Time;\n"
"uniform highp vec4 cc_SinTime;\n"
"uniform highp vec4 cc_CosTime;\n"
"uniform highp vec4 cc_Random01;\n\n"
"uniform " XSTR(CC_SHADER_COLOR_PRECISION) " sampler2D cc_MainTexture;\n\n"
"uniform " XSTR(CC_SHADER_COLOR_PRECISION) " sampler2D cc_NormalMapTexture;\n\n"
"varying " XSTR(CC_SHADER_COLOR_PRECISION) " vec4 cc_FragColor;\n"
"varying highp vec2 cc_FragTexCoord1;\n"
"varying highp vec2 cc_FragTexCoord2;\n\n"
"// End Cocos2D shader header.\n\n";
static const GLchar *CCVertexShaderHeader =
"#ifdef GL_ES\n"
"precision highp float;\n\n"
"#endif\n\n"
"#define CC_NODE_RENDER_SUBPIXEL " XSTR(CC_NODE_RENDER_SUBPIXEL) "\n"
"attribute highp vec4 cc_Position;\n"
"attribute highp vec2 cc_TexCoord1;\n"
"attribute highp vec2 cc_TexCoord2;\n"
"attribute highp vec4 cc_Color;\n\n"
"// End Cocos2D vertex shader header.\n\n";
static const GLchar *CCFragmentShaderHeader =
"#ifdef GL_ES\n"
"precision " XSTR(CC_SHADER_DEFAULT_FRAGMENT_PRECISION) " float;\n"
"#endif\n\n"
"// End Cocos2D fragment shader header.\n\n";
static NSString *CCDefaultVShader =
#"void main(){\n"
#" gl_Position = cc_Position;\n"
#"#if !CC_NODE_RENDER_SUBPIXEL\n"
#" vec2 pixelPos = (0.5*gl_Position.xy/gl_Position.w + 0.5)*cc_ViewSizeInPixels;\n"
#" gl_Position.xy = (2.0*floor(pixelPos)/cc_ViewSizeInPixels - 1.0)*gl_Position.w;\n"
#"#endif\n\n"
#" cc_FragColor = clamp(cc_Color, 0.0, 1.0);\n"
#" cc_FragTexCoord1 = cc_TexCoord1;\n"
#" cc_FragTexCoord2 = cc_TexCoord2;\n"
#"}\n";
typedef void (* GetShaderivFunc) (GLuint shader, GLenum pname, GLint* param);
typedef void (* GetShaderInfoLogFunc) (GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
static BOOL
CCCheckShaderError(GLint obj, GLenum status, GetShaderivFunc getiv, GetShaderInfoLogFunc getInfoLog)
{
GLint success;
getiv(obj, status, &success);
if(!success){
GLint length;
getiv(obj, GL_INFO_LOG_LENGTH, &length);
char *log = (char *)alloca(length);
getInfoLog(obj, length, NULL, log);
fprintf(stderr, "Shader compile error for 0x%04X: %s\n", status, log);
return NO;
} else {
return YES;
}
}
static const GLchar *
CCShaderTypeHeader(GLenum type)
{
switch(type){
case GL_VERTEX_SHADER: return CCVertexShaderHeader;
case GL_FRAGMENT_SHADER: return CCFragmentShaderHeader;
default: NSCAssert(NO, #"Bad shader type enumeration."); return NULL;
}
}
static GLint
CompileShader(GLenum type, const char *source)
{
GLint shader = glCreateShader(type);
const GLchar *sources[] = {
CCShaderHeader,
CCShaderTypeHeader(type),
source,
};
glShaderSource(shader, 3, sources, NULL);
glCompileShader(shader);
NSCAssert(CCCheckShaderError(shader, GL_COMPILE_STATUS, glGetShaderiv, glGetShaderInfoLog), #"Error compiling shader");
return shader;
}
#interface CCShaderCache : CCCache #end
#implementation CCShaderCache
-(id)createSharedDataForKey:(id<NSCopying>)key
{
NSString *shaderName = (NSString *)key;
NSString *fragmentName = [shaderName stringByAppendingPathExtension:#"fsh"];
NSString *fragmentPath = [[CCFileUtils sharedFileUtils] fullPathForFilename:fragmentName];
NSAssert(fragmentPath, #"Failed to find '%#'.", fragmentName);
NSString *fragmentSource = [NSString stringWithContentsOfFile:fragmentPath encoding:NSUTF8StringEncoding error:nil];
NSString *vertexName = [shaderName stringByAppendingPathExtension:#"vsh"];
NSString *vertexPath = [[CCFileUtils sharedFileUtils] fullPathForFilename:vertexName];
NSString *vertexSource = (vertexPath ? [NSString stringWithContentsOfFile:vertexPath encoding:NSUTF8StringEncoding error:nil] : CCDefaultVShader);
CCShader *shader = [[CCShader alloc] initWithVertexShaderSource:vertexSource fragmentShaderSource:fragmentSource];
shader.debugName = #"shaderName";
return shader;
}
-(id)createPublicObjectForSharedData:(id)data
{
return [data copy];
}
#end
#implementation CCShader {
BOOL _ownsProgram;
}
+(GLuint)createVAOforCCVertexBuffer:(GLuint)vbo elementBuffer:(GLuint)ebo
{
glPushGroupMarkerEXT(0, "CCShader: Creating vertex buffer");
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(CCAttributePosition);
glEnableVertexAttribArray(CCAttributeTexCoord1);
glEnableVertexAttribArray(CCAttributeTexCoord2);
glEnableVertexAttribArray(CCAttributeColor);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(CCAttributePosition, 4, GL_FLOAT, GL_FALSE, sizeof(CCVertex), (void *)offsetof(CCVertex, position));
glVertexAttribPointer(CCAttributeTexCoord1, 2, GL_FLOAT, GL_FALSE, sizeof(CCVertex), (void *)offsetof(CCVertex, texCoord1));
glVertexAttribPointer(CCAttributeTexCoord2, 2, GL_FLOAT, GL_FALSE, sizeof(CCVertex), (void *)offsetof(CCVertex, texCoord2));
glVertexAttribPointer(CCAttributeColor, 4, GL_FLOAT, GL_FALSE, sizeof(CCVertex), (void *)offsetof(CCVertex, color));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glPopGroupMarkerEXT();
return vao;
}
//MARK: Uniform Setters:
static CCUniformSetter
SetFloat(NSString *name, GLint location)
{
return ^(CCRenderer *renderer, NSDictionary *shaderUniforms, NSDictionary *globalShaderUniforms){
NSNumber *value = shaderUniforms[name] ?: globalShaderUniforms[name] ?: #(0.0);
NSCAssert([value isKindOfClass:[NSNumber class]], #"Shader uniform '%#' value must be wrapped in a NSNumber.", name);
glUniform1f(location, value.floatValue);
};
}
static CCUniformSetter
SetVec2(NSString *name, GLint location)
{
NSString *textureName = nil;
bool pixelSize = [name hasSuffix:#"PixelSize"];
if(pixelSize){
textureName = [name substringToIndex:name.length - #"PixelSize".length];
} else if([name hasSuffix:#"Size"]){
textureName = [name substringToIndex:name.length - #"Size".length];
}
return ^(CCRenderer *renderer, NSDictionary *shaderUniforms, NSDictionary *globalShaderUniforms){
NSValue *value = shaderUniforms[name] ?: globalShaderUniforms[name];
// Fall back on looking up the actual texture size if the name matches a texture.
if(value == nil && textureName){
CCTexture *texture = shaderUniforms[textureName] ?: globalShaderUniforms[textureName];
GLKVector2 sizeInPixels = GLKVector2Make(texture.pixelWidth, texture.pixelHeight);
GLKVector2 size = GLKVector2MultiplyScalar(sizeInPixels, pixelSize ? 1.0 : 1.0/texture.contentScale);
value = [NSValue valueWithGLKVector2:size];
}
// Finally fall back on 0.
if(value == nil) value = [NSValue valueWithGLKVector2:GLKVector2Make(0.0f, 0.0f)];
NSCAssert([value isKindOfClass:[NSValue class]], #"Shader uniform '%#' value must be wrapped in a NSValue.", name);
if(strcmp(value.objCType, #encode(GLKVector2)) == 0){
GLKVector2 v; [value getValue:&v];
glUniform2f(location, v.x, v.y);
} else if(strcmp(value.objCType, #encode(CGPoint)) == 0){
CGPoint v = {}; [value getValue:&v];
glUniform2f(location, v.x, v.y);
} else if(strcmp(value.objCType, #encode(CGSize)) == 0){
CGSize v = {}; [value getValue:&v];
glUniform2f(location, v.width, v.height);
} else {
NSCAssert(NO, #"Shader uniformm 'vec2 %#' value must be passed using [NSValue valueWithGLKVector2:], [NSValue valueWithCGPoint:], or [NSValue valueWithCGSize:]", name);
}
};
}
static CCUniformSetter
SetVec3(NSString *name, GLint location)
{
return ^(CCRenderer *renderer, NSDictionary *shaderUniforms, NSDictionary *globalShaderUniforms){
NSValue *value = shaderUniforms[name] ?: globalShaderUniforms[name] ?: [NSValue valueWithGLKVector3:GLKVector3Make(0.0f, 0.0f, 0.0f)];
NSCAssert([value isKindOfClass:[NSValue class]], #"Shader uniform '%#' value must be wrapped in a NSValue.", name);
NSCAssert(strcmp(value.objCType, #encode(GLKVector3)) == 0, #"Shader uniformm 'vec3 %#' value must be passed using [NSValue valueWithGLKVector3:]", name);
GLKVector3 v; [value getValue:&v];
glUniform3f(location, v.x, v.y, v.z);
};
}
static CCUniformSetter
SetVec4(NSString *name, GLint location)
{
return ^(CCRenderer *renderer, NSDictionary *shaderUniforms, NSDictionary *globalShaderUniforms){
NSValue *value = shaderUniforms[name] ?: globalShaderUniforms[name] ?: [NSValue valueWithGLKVector4:GLKVector4Make(0.0f, 0.0f, 0.0f, 1.0f)];
if([value isKindOfClass:[NSValue class]]){
NSCAssert(strcmp([(NSValue *)value objCType], #encode(GLKVector4)) == 0, #"Shader uniformm 'vec4 %#' value must be passed using [NSValue valueWithGLKVector4:].", name);
GLKVector4 v; [value getValue:&v];
glUniform4f(location, v.x, v.y, v.z, v.w);
} else if([value isKindOfClass:[CCColor class]]){
GLKVector4 v = [(CCColor *)value glkVector4];
glUniform4f(location, v.x, v.y, v.z, v.w);
} else {
NSCAssert(NO, #"Shader uniformm 'vec4 %#' value must be passed using [NSValue valueWithGLKVector4:] or a CCColor object.", name);
}
};
}
static CCUniformSetter
SetMat4(NSString *name, GLint location)
{
return ^(CCRenderer *renderer, NSDictionary *shaderUniforms, NSDictionary *globalShaderUniforms){
NSValue *value = shaderUniforms[name] ?: globalShaderUniforms[name] ?: [NSValue valueWithGLKMatrix4:GLKMatrix4Identity];
NSCAssert([value isKindOfClass:[NSValue class]], #"Shader uniform '%#' value must be wrapped in a NSValue.", name);
NSCAssert(strcmp(value.objCType, #encode(GLKMatrix4)) == 0, #"Shader uniformm 'mat4 %#' value must be passed using [NSValue valueWithGLKMatrix4:]", name);
GLKMatrix4 m; [value getValue:&m];
glUniformMatrix4fv(location, 1, GL_FALSE, m.m);
};
}
-(NSDictionary *)uniformSettersForProgram:(GLuint)program
{
NSMutableDictionary *uniformSetters = [NSMutableDictionary dictionary];
glUseProgram(program);
GLint count = 0;
glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &count);
int textureUnit = 0;
for(int i=0; i<count; i++){
GLchar cname[256];
GLsizei length = 0;
GLsizei size = 0;
GLenum type = 0;
glGetActiveUniform(program, i, sizeof(cname), &length, &size, &type, cname);
NSAssert(size == 1, #"Uniform arrays not supported. (yet?)");
NSString *name = #(cname);
GLint location = glGetUniformLocation(program, cname);
// Setup a block that is responsible for binding that uniform variable's value.
switch(type){
default: NSAssert(NO, #"Uniform type not supported. (yet?)");
case GL_FLOAT: uniformSetters[name] = SetFloat(name, location); break;
case GL_FLOAT_VEC2: uniformSetters[name] = SetVec2(name, location); break;
case GL_FLOAT_VEC3: uniformSetters[name] = SetVec3(name, location); break;
case GL_FLOAT_VEC4: uniformSetters[name] = SetVec4(name, location); break;
case GL_FLOAT_MAT4: uniformSetters[name] = SetMat4(name, location); break;
case GL_SAMPLER_2D: {
// Sampler setters are handled a differently since the real work is binding the texture and not setting the uniform value.
uniformSetters[name] = ^(CCRenderer *renderer, NSDictionary *shaderUniforms, NSDictionary *globalShaderUniforms){
CCTexture *texture = shaderUniforms[name] ?: globalShaderUniforms[name] ?: [CCTexture none];
NSAssert([texture isKindOfClass:[CCTexture class]], #"Shader uniform '%#' value must be a CCTexture object.", name);
// Bind the texture to the texture unit for the uniform.
glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(GL_TEXTURE_2D, texture.name);
};
// Bind the texture unit at init time.
glUniform1i(location, textureUnit);
textureUnit++;
}
}
}
return uniformSetters;
}
//MARK: Init Methods:
-(instancetype)initWithProgram:(GLuint)program uniformSetters:(NSDictionary *)uniformSetters ownsProgram:(BOOL)ownsProgram
{
if((self = [super init])){
_program = program;
_uniformSetters = uniformSetters;
_ownsProgram = ownsProgram;
}
return self;
}
-(instancetype)initWithVertexShaderSource:(NSString *)vertexSource fragmentShaderSource:(NSString *)fragmentSource
{
glPushGroupMarkerEXT(0, "CCShader: Init");
GLuint program = glCreateProgram();
glBindAttribLocation(program, CCAttributePosition, "cc_Position");
glBindAttribLocation(program, CCAttributeTexCoord1, "cc_TexCoord1");
glBindAttribLocation(program, CCAttributeTexCoord2, "cc_TexCoord2");
glBindAttribLocation(program, CCAttributeColor, "cc_Color");
GLint vshader = CompileShader(GL_VERTEX_SHADER, vertexSource.UTF8String);
glAttachShader(program, vshader);
GLint fshader = CompileShader(GL_FRAGMENT_SHADER, fragmentSource.UTF8String);
glAttachShader(program, fshader);
glLinkProgram(program);
NSCAssert(CCCheckShaderError(program, GL_LINK_STATUS, glGetProgramiv, glGetProgramInfoLog), #"Error linking shader program");
glDeleteShader(vshader);
glDeleteShader(fshader);
glPopGroupMarkerEXT();
return [self initWithProgram:program uniformSetters:[self uniformSettersForProgram:program] ownsProgram:YES];
}
-(instancetype)initWithFragmentShaderSource:(NSString *)source
{
return [self initWithVertexShaderSource:CCDefaultVShader fragmentShaderSource:source];
}
- (void)dealloc
{
CCLOGINFO( #"cocos2d: deallocing %#", self);
if(_ownsProgram && _program) glDeleteProgram(_program);
}
-(instancetype)copyWithZone:(NSZone *)zone
{
return [[CCShader allocWithZone:zone] initWithProgram:_program uniformSetters:_uniformSetters ownsProgram:NO];
}
static CCShaderCache *CC_SHADER_CACHE = nil;
static CCShader *CC_SHADER_POS_COLOR = nil;
static CCShader *CC_SHADER_POS_TEX_COLOR = nil;
static CCShader *CC_SHADER_POS_TEXA8_COLOR = nil;
static CCShader *CC_SHADER_POS_TEX_COLOR_ALPHA_TEST = nil;
+(void)initialize
{
// +initialize may be called due to loading a subclass.
if(self != [CCShader class]) return;
CC_SHADER_CACHE = [[CCShaderCache alloc] init];
// Setup the builtin shaders.
CC_SHADER_POS_COLOR = [[self alloc] initWithFragmentShaderSource:#"void main(){gl_FragColor = cc_FragColor;}"];
CC_SHADER_POS_COLOR.debugName = #"CCPositionColorShader";
CC_SHADER_POS_TEX_COLOR = [[self alloc] initWithFragmentShaderSource:#"void main(){gl_FragColor = cc_FragColor*texture2D(cc_MainTexture, cc_FragTexCoord1);}"];
CC_SHADER_POS_TEX_COLOR.debugName = #"CCPositionTextureColorShader";
CC_SHADER_POS_TEXA8_COLOR = [[self alloc] initWithFragmentShaderSource:#"void main(){gl_FragColor = cc_FragColor*texture2D(cc_MainTexture, cc_FragTexCoord1).a;}"];
CC_SHADER_POS_TEXA8_COLOR.debugName = #"CCPositionTextureA8ColorShader";
CC_SHADER_POS_TEX_COLOR_ALPHA_TEST = [[self alloc] initWithFragmentShaderSource:CC_GLSL(
uniform float cc_AlphaTestValue;
void main(){
vec4 tex = texture2D(cc_MainTexture, cc_FragTexCoord1);
if(tex.a <= cc_AlphaTestValue) discard;
gl_FragColor = cc_FragColor*tex;
}
)];
CC_SHADER_POS_TEX_COLOR_ALPHA_TEST.debugName = #"CCPositionTextureColorAlphaTestShader";
}
+(instancetype)positionColorShader
{
return CC_SHADER_POS_COLOR;
}
+(instancetype)positionTextureColorShader
{
return CC_SHADER_POS_TEX_COLOR;
}
+(instancetype)positionTextureColorAlphaTestShader
{
return CC_SHADER_POS_TEX_COLOR_ALPHA_TEST;
}
+(instancetype)positionTextureA8ColorShader
{
return CC_SHADER_POS_TEXA8_COLOR;
}
+(instancetype)shaderNamed:(NSString *)shaderName
{
return [CC_SHADER_CACHE objectForKey:shaderName];
}
#end
you can get the example code from:cocos3d following: the CC3DemoMultiScene in File Projects
SECOND EDIT:
I read several responses on StackOverflow and in this forum: Cocos 2D Forum, I had to re install xCode, I don't know what happened? but now, not show me the CCShader Error, show me:
OpenGL error GL_INVALID_OPERATION detected at -[CCRenderer(NoARCPrivate) setRenderState:] 232
how is the best way for show 1 Scene of Cocos 3D in 2 different ViewControllers?
Thanks Again!!
After of many searches and investigations, The reason this causes trouble is because this causes the AppDelegate applicationDidBecomeActive: method (which references CCDirector.sharedDirector singleton) to be invoked before the MainViewController createGLView method (which initializes the CCDirector.sharedDirector singleton).
The reference to the uninitialized CCDirector.sharedDirector singleton in AppDelegate applicationDidBecomeActive: triggers a whole bunch of Cocos2D OpenGL ES initialization before the OpenGL context has been set up correctly, causing a bunch of shader loading activity to fail.
The best way to fix this is to ensure that the code found in the MainViewController createGLView method is run before any references to the CCDirector.sharedDirector singleton are made elsewhere.
We can also side-step the problem in the short-term by commenting out the code in the AppDelegate applicationDidBecomeActive: method, but that might affect the behaviour of your app as it moves in and out of the background.
like the answers from #Bill Hollings in this questions:
Error CompileShader in Xcode 7.1.1 on iOS 9? and
Error cocos3d + Storyboard?
I configured and tried an example DennisCocos3D Prueba (dropbox)
or try with:
in MainViewController .m file:
-(CCGLView*) createGLView {
// Create the view first, since it creates the GL context, which CCDirector expects during init.
CCGLView* glView = [CCGLView viewWithFrame: _cc3FrameView.bounds
pixelFormat: kEAGLColorFormatRGBA8
depthFormat: GL_DEPTH24_STENCIL8 // Shadow volumes require a stencil
preserveBackbuffer: NO
numberOfSamples: 1];
CCDirector* director = CCDirector.sharedDirector;
director.animationInterval = (1.0f / kAnimationFrameRate);
director.displayStats = YES;
director.view = glView;
// Run the initial static 2D intro scene
[director runWithScene: [[self makeIntroScene] asCCScene]];
if(![[CCDirector sharedDirector] runningScene])
{
[[CCDirector sharedDirector] runWithScene:[[self makeIntroScene] asCCScene]];
}
else
{
[[CCDirector sharedDirector] startAnimation];
[[CCDirector sharedDirector] replaceScene:[[self makeIntroScene] asCCScene]];
}
return glView;
}
Related
Shader doesn't work - OpenGL ES
I have created a program that allows me to display 3D objects and now I want to make a cut in relation to another object. Here is my result : screen. The screen shows that we can see through the cut portion. So I decided to use a shader to fill this cut part. I tried to load a shader and then to use it in a glUniform3f but that doesn't work. I did several searches on the internet, without results. Here is my class to load a shader: - (id)initWithVertexShaderFilename:(NSString *)vShaderFilename fragmentShaderFilename:(NSString *)fShaderFilename { NSLog(fShaderFilename); if (self = [super init]) { attributes = [[NSMutableArray alloc] init]; NSString *vertShaderPathname, *fragShaderPathname; program = glCreateProgram(); vertShaderPathname =[[NSBundle mainBundle] pathForResource:vShaderFilename ofType:#"vsh" inDirectory:#"Shader"]; if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) NSLog(#"Failed to compile vertex shader"); else NSLog(#"Vertex Shader OK"); fragShaderPathname = [[NSBundle mainBundle] pathForResource:fShaderFilename ofType:#"fsh" inDirectory:#"Shader"]; if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) NSLog(#"Failed to compile fragment shader"); else NSLog(#"Fragment shader OK"); glAttachShader(program, vertShader); glAttachShader(program, fragShader); } return self; } - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file { NSLog(#"bonjour"); GLint status; const GLchar *source; source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; if (!source) { NSLog(#"Failed to load vertex shader"); return NO; } *shader = glCreateShader(type); glShaderSource(*shader, 1, &source, NULL); glCompileShader(*shader); glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); NSString *intString = [NSString stringWithFormat:#"%d", status]; return status = GL_TRUE; } #pragma mark - - (void)addAttribute:(NSString *)attributeName { if (![attributes containsObject:attributeName]) { [attributes addObject:attributeName]; glBindAttribLocation(program, [attributes indexOfObject:attributeName], [attributeName UTF8String]); } } - (GLuint)attributeIndex:(NSString *)attributeName { return [attributes indexOfObject:attributeName]; } - (GLuint)uniformIndex:(NSString *)uniformName { return glGetUniformLocation(program, [uniformName UTF8String]); } #pragma mark - - (BOOL)link { GLint status; glLinkProgram(program); glValidateProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &status); if (status == GL_FALSE) return NO; if (vertShader) glDeleteShader(vertShader); if (fragShader) glDeleteShader(fragShader); return YES; } - (void)use { glUseProgram(program); } Here is the function to initialize my shaders in the main class: - (void)setup { GLShader *theProgram = [[GLShader alloc] initWithVertexShaderFilename:#"shader" fragmentShaderFilename:#"shader"]; self.program = theProgram; [self.program addAttribute:#"position"]; [self.program addAttribute:#"textureCoordinates"]; if (![self.program link]) { NSLog(#"Link failed"); NSString *progLog = [self.program programLog]; NSLog(#"Program Log: %#", progLog); NSString *fragLog = [self.program fragmentShaderLog]; NSLog(#"Frag Log: %#", fragLog); NSString *vertLog = [self.program vertexShaderLog]; NSLog(#"Vert Log: %#", vertLog); //[(GLView *)self.view stopAnimation]; self.program = nil; } textureCoordinateAttribute = [program attributeIndex:#"textureCoordinates"]; colorUniform = [program uniformIndex:#"uColor"]; textureUniform = [program uniformIndex:#"texture"]; //colorUniform = glGetUniformLocation(self.program, "uColor"); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ZERO); } Here is the function where I want to use my shader: -(void) draw { [self.program use]; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glDepthMask(true); lUniform3f(colorUniform,1.0, 1.0, 0.5); [self drawSubtraction:image1 with:image2]; } Here is my fragment shader: precision highp float; uniform vec3 uColor; uniform vec3 uLight; varying vec3 vNormal; const float alpha = 0.7; void main(void) { float val = dot( vNormal, uLight ) * 0.4 + 0.6; gl_FragColor = vec4( uColor * val, alpha); } Am I doing something wrong ? Someone has an idea that could help me ? Thanks.
Your shader code looks ok. Make sure you are passing in the "textureCoordinates" attribute correctly to the vertex shader. You will need to call glEnableVertexAttribArray() and glVertexAttribPointer() at some point of the initialization. Depending on how you are rendering the models you might need to ensure you are passing in vertices correctly as well. Also i'm assuming [self drawSubtraction:image1 with:image2] calls glDrawArrays() or glDrawElements() at some point. The Xcode default OpenGL game project is a great place to start for loading shaders too if you want a project to compare against.
NSMutableString:rangeOfString: weird NSRange result
Trying to figure out why NSMutableString:rangeOfString: is returning really weird results. NSLog is showing me a result like this: location=9223372036854775807 length=0:This is a test My test string does not contain "###", so I'd expect location=0 length=0. The weird location keeps coming up until the string actually contains "###" then location and length are correct. What am I missing in the below code snippet? ServerPacketMotd.h typedef struct _serverPacketMotdStruct { int8_t type; /* SP_MOTD */ int8_t pad1; int8_t pad2; int8_t pad3; int8_t line[80]; } serverPacketMotdStruct; ServerPacketMotd.m #import "ServerPacketMotd.h" #interface ServerPacketMotd() { NSMutableString *buffer; } #end #implementation ServerPacketMotd - (id)init { if( !( self = [super init] ) ) return nil; buffer = [[NSMutableString alloc] init]; return self; } - (NSMutableData *)handlePacket:(NSData *)data withTag:(long)tag { serverPacketMotdStruct gamePacket; uint16_t size = sizeof(serverPacketMotdStruct); NSRange packetWindow = NSMakeRange(0, size); NSRange atAtAt = NSMakeRange(0,0); while (expression) { [data getBytes:&gamePacket range:packetWindow]; [buffer appendFormat:#"%s\n", gamePacket.line]; atAtAt = [buffer rangeOfString:#"###"]; NSLog(#"XXX location=%lu length=%lu:%#", atAtAt.location, atAtAt.length, buffer); }
Check if atAtAt.location == NSNotFound. A location of 0 means the string was found at location 0, it doesn't mean it wan't found.
Segmentation Fault 11 | CGEventTap application stops processing mouse events after arbitrary amount of time.
The purpose of this application is to run in the background 24/7 and lock the mouse in the center of the screen. It's for work with a series of flash programs to simulate joystick-style movement for the mouse. I've already attempted to use other methods built into Cocoa/Quartz in order to accomplish this, and none of them worked for my purpose, so this is the way I have to do it. I have been trying to figure out why, after a seemingly random amount of time, this program simply stops restricting the mouse. The program doesn't give an error or anything like that, it just stops working. The force-quit screen DOES say "Not Responding", however, many of my mouse modifying scripts, including this one, always read as "not responding" and they keep functioning. Here's the code: code removed, check below for updated code. Final Update Ken Thomases gave me the right answer, I've updated my code based on his suggestions. Here's the final code that I've gotten to work flawlessly (this ran for 12+ hours without a hitch before I manually stopped it): #import <Cocoa/Cocoa.h> #import <CoreMedia/CoreMedia.h> int screen_width, screen_height; struct event_tap_data_struct { CFMachPortRef event_tap; float speed_modifier; }; CGEventRef mouse_filter(CGEventTapProxy proxy, CGEventType type, CGEventRef event, struct event_tap_data_struct *); int screen_res(int); int main(int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; screen_width = screen_res(0); screen_height = screen_res(1); CFRunLoopSourceRef runLoopSource; CGEventMask event_mask = kCGEventMaskForAllEvents; CGSetLocalEventsSuppressionInterval(0); CFMachPortRef eventTap; struct event_tap_data_struct event_tap_data = {eventTap,0.2}; eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 0, event_mask, mouse_filter, &event_tap_data); event_tap_data.event_tap = eventTap; if (!eventTap) { NSLog(#"Couldn't create event tap!"); exit(1); } runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, event_tap_data.event_tap, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes); CGEventTapEnable(event_tap_data.event_tap, true); CFRunLoopRun(); CFRelease(eventTap); CFRelease(runLoopSource); [pool release]; exit(0); } int screen_res(int width_or_height) { NSRect screenRect; NSArray *screenArray = [NSScreen screens]; unsigned screenCount = (unsigned)[screenArray count]; for (unsigned index = 0; index < screenCount; index++) { NSScreen *screen = [screenArray objectAtIndex: index]; screenRect = [screen visibleFrame]; } int resolution_array[] = {(int)CGDisplayPixelsWide(CGMainDisplayID()),(int)CGDisplayPixelsHigh(CGMainDisplayID())}; if(width_or_height==0){ return resolution_array[0]; }else { return resolution_array[1]; } } CGEventRef mouse_filter(CGEventTapProxy proxy, CGEventType type, CGEventRef event, struct event_tap_data_struct *event_tap_data) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; if (type == kCGEventTapDisabledByTimeout || type == kCGEventTapDisabledByUserInput) { CGEventTapEnable(event_tap_data->event_tap,true); return event; } else if (type == kCGEventMouseMoved || type == kCGEventLeftMouseDragged || type == kCGEventRightMouseDragged || type == kCGEventOtherMouseDragged){ CGPoint point = CGEventGetLocation(event); NSPoint old_point; CGPoint target; int tX = point.x; int tY = point.y; float oX = screen_width/2; float oY = screen_height/2; float dX = tX-oX; float dY = tY-oY; old_point.x = floor(oX); old_point.y = floor(oY); dX*=2, dY*=2; tX = round(oX + dX); tY = round(oY + dY); target = CGPointMake(tX, tY); CGWarpMouseCursorPosition(old_point); CGEventSetLocation(event,target); } [pool release]; return event; } (first) Update: The program is still crashing, but I have now run it as an executable and received an error code. When it terminates, the console logs "Segmentation Fault: 11". I've been trying to discover what this means, however it appears to be an impressively broad term, and I've yet to hone in on something useful. Here is the new code I am using: #import <Cocoa/Cocoa.h> #import <CoreMedia/CoreMedia.h> int screen_width, screen_height; struct event_tap_data_struct { CFMachPortRef event_tap; float speed_modifier; }; CGEventRef mouse_filter(CGEventTapProxy proxy, CGEventType type, CGEventRef event, struct event_tap_data_struct *); int screen_res(int); int main(int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; screen_width = screen_res(0); screen_height = screen_res(1); CFRunLoopSourceRef runLoopSource; CGEventMask event_mask; event_mask = CGEventMaskBit(kCGEventMouseMoved) | CGEventMaskBit(kCGEventLeftMouseDragged) | CGEventMaskBit(kCGEventRightMouseDragged) | CGEventMaskBit(kCGEventOtherMouseDragged); CGSetLocalEventsSuppressionInterval(0); CFMachPortRef eventTap; CFMachPortRef *eventTapPtr = &eventTap; struct event_tap_data_struct event_tap_data = {*eventTapPtr,0.2}; eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 0, event_mask, mouse_filter, &event_tap_data); if (!eventTap) { NSLog(#"Couldn't create event tap!"); exit(1); } runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes); CGEventTapEnable(eventTap, true); CFRunLoopRun(); CFRelease(eventTap); CFRelease(runLoopSource); [pool release]; exit(0); } int screen_res(int width_or_height) { NSRect screenRect; NSArray *screenArray = [NSScreen screens]; unsigned screenCount = (unsigned)[screenArray count]; for (unsigned index = 0; index < screenCount; index++) { NSScreen *screen = [screenArray objectAtIndex: index]; screenRect = [screen visibleFrame]; } int resolution_array[] = {(int)CGDisplayPixelsWide(CGMainDisplayID()),(int)CGDisplayPixelsHigh(CGMainDisplayID())}; if(width_or_height==0){ return resolution_array[0]; }else { return resolution_array[1]; } } CGEventRef mouse_filter(CGEventTapProxy proxy, CGEventType type, CGEventRef event, struct event_tap_data_struct *event_tap_data) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; if (type == kCGEventTapDisabledByTimeout || type == kCGEventTapDisabledByUserInput) { CGEventTapEnable(event_tap_data->event_tap,true); } CGPoint point = CGEventGetLocation(event); NSPoint old_point; CGPoint target; int tX = point.x; int tY = point.y; float oX = screen_width/2; float oY = screen_height/2; float dX = tX-oX; float dY = tY-oY; old_point.x = floor(oX); old_point.y = floor(oY); dX*=2, dY*=2; tX = round(oX + dX); tY = round(oY + dY); target = CGPointMake(tX, tY); CGWarpMouseCursorPosition(old_point); CGEventSetLocation(event,target); [pool release]; return event; }
You need to re-enable your event tap when it receives kCGEventTapDisabledByTimeout or kCGEventTapDisabledByUserInput. Update: here are your lines and how they're (failing to) work: CFMachPortRef eventTap; // uninitialized value CFMachPortRef *eventTapPtr = &eventTap; // pointer to eventTap struct event_tap_data_struct event_tap_data = {*eventTapPtr,0.2}; // dereferences pointer, copying uninitialized value into struct eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 0, event_mask, mouse_filter, &event_tap_data); // sets eventTap but has no effect on event_tap_data
AudioUnit tone generator is giving me a chirp at the end of each tone generated
I'm creating a old school music emulator for the old GWBasic PLAY command. To that end I have a tone generator and a music player. Between each of the notes played I'm getting a chirp sound that mucking things up. Below are both of my classes: ToneGen.h #import <Foundation/Foundation.h> #interface ToneGen : NSObject #property (nonatomic) id delegate; #property (nonatomic) double frequency; #property (nonatomic) double sampleRate; #property (nonatomic) double theta; - (void)play:(float)ms; - (void)play; - (void)stop; #end ToneGen.m #import <AudioUnit/AudioUnit.h> #import "ToneGen.h" OSStatus RenderTone( void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); void ToneInterruptionListener(void *inClientData, UInt32 inInterruptionState); #interface ToneGen() #property (nonatomic) AudioComponentInstance toneUnit; #property (nonatomic) NSTimer *timer; - (void)createToneUnit; #end #implementation ToneGen #synthesize toneUnit = _toneUnit; #synthesize timer = _timer; #synthesize delegate = _delegate; #synthesize frequency = _frequency; #synthesize sampleRate = _sampleRate; #synthesize theta = _theta; - (id) init { self = [super init]; if (self) { self.sampleRate = 44100; self.frequency = 1440.0f; return self; } return nil; } - (void)play:(float)ms { [self play]; self.timer = [NSTimer scheduledTimerWithTimeInterval:(ms / 100) target:self selector:#selector(stop) userInfo:nil repeats:NO]; [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; } - (void)play { if (!self.toneUnit) { [self createToneUnit]; // Stop changing parameters on the unit OSErr err = AudioUnitInitialize(self.toneUnit); if (err) DLog(#"Error initializing unit"); // Start playback err = AudioOutputUnitStart(self.toneUnit); if (err) DLog(#"Error starting unit"); } } - (void)stop { [self.timer invalidate]; self.timer = nil; if (self.toneUnit) { AudioOutputUnitStop(self.toneUnit); AudioUnitUninitialize(self.toneUnit); AudioComponentInstanceDispose(self.toneUnit); self.toneUnit = nil; } if(self.delegate && [self.delegate respondsToSelector:#selector(toneStop)]) { [self.delegate performSelector:#selector(toneStop)]; } } - (void)createToneUnit { AudioComponentDescription defaultOutputDescription; defaultOutputDescription.componentType = kAudioUnitType_Output; defaultOutputDescription.componentSubType = kAudioUnitSubType_DefaultOutput; defaultOutputDescription.componentManufacturer = kAudioUnitManufacturer_Apple; defaultOutputDescription.componentFlags = 0; defaultOutputDescription.componentFlagsMask = 0; // Get the default playback output unit AudioComponent defaultOutput = AudioComponentFindNext(NULL, &defaultOutputDescription); if (!defaultOutput) DLog(#"Can't find default output"); // Create a new unit based on this that we'll use for output OSErr err = AudioComponentInstanceNew(defaultOutput, &_toneUnit); if (err) DLog(#"Error creating unit"); // Set our tone rendering function on the unit AURenderCallbackStruct input; input.inputProc = RenderTone; input.inputProcRefCon = (__bridge void*)self; err = AudioUnitSetProperty(self.toneUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(input)); if (err) DLog(#"Error setting callback"); // Set the format to 32 bit, single channel, floating point, linear PCM const int four_bytes_per_float = 4; const int eight_bits_per_byte = 8; AudioStreamBasicDescription streamFormat; streamFormat.mSampleRate = self.sampleRate; streamFormat.mFormatID = kAudioFormatLinearPCM; streamFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; streamFormat.mBytesPerPacket = four_bytes_per_float; streamFormat.mFramesPerPacket = 1; streamFormat.mBytesPerFrame = four_bytes_per_float; streamFormat.mChannelsPerFrame = 1; streamFormat.mBitsPerChannel = four_bytes_per_float * eight_bits_per_byte; err = AudioUnitSetProperty (self.toneUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription)); if (err) DLog(#"Error setting stream format"); } #end OSStatus RenderTone( void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { // Fixed amplitude is good enough for our purposes const double amplitude = 0.25; // Get the tone parameters out of the view controller ToneGen *toneGen = (__bridge ToneGen *)inRefCon; double theta = toneGen.theta; double theta_increment = 2.0 * M_PI * toneGen.frequency / toneGen.sampleRate; // This is a mono tone generator so we only need the first buffer const int channel = 0; Float32 *buffer = (Float32 *)ioData->mBuffers[channel].mData; // Generate the samples for (UInt32 frame = 0; frame < inNumberFrames; frame++) { buffer[frame] = sin(theta) * amplitude; theta += theta_increment; if (theta > 2.0 * M_PI) { theta -= 2.0 * M_PI; } } // Store the theta back in the view controller toneGen.theta = theta; return noErr; } void ToneInterruptionListener(void *inClientData, UInt32 inInterruptionState) { ToneGen *toneGen = (__bridge ToneGen *)inClientData; [toneGen stop]; } Music.h #import <Foundation/Foundation.h> #interface Music : NSObject - (void) play:(NSString *)music; - (void) stop; #end Music.m #import "Music.h" #import "ToneGen.h" #interface Music() #property (nonatomic, readonly) ToneGen *toneGen; #property (nonatomic, assign) int octive; #property (nonatomic, assign) int tempo; #property (nonatomic, assign) int length; #property (nonatomic, strong) NSData *music; #property (nonatomic, assign) int dataPos; #property (nonatomic, assign) BOOL isPlaying; - (void)playNote; #end #implementation Music #synthesize toneGen = _toneGen; - (ToneGen*)toneGen { if (_toneGen == nil) { _toneGen = [[ToneGen alloc] init]; _toneGen.delegate = self; } return _toneGen; } #synthesize octive = _octive; - (void)setOctive:(int)octive { // Sinity Check if (octive < 0) octive = 0; if (octive > 6) octive = 6; _octive = octive; } #synthesize tempo = _tempo; - (void)setTempo:(int)tempo { // Sinity Check if (tempo < 30) tempo = 30; if (tempo > 255) tempo = 255; _tempo = tempo; } #synthesize length = _length; - (void)setLength:(int)length { // Sinity Check if (length < 1) length = 1; if (length > 64) length = 64; _length = length; } #synthesize music = _music; #synthesize dataPos = _dataPos; #synthesize isPlaying = _isPlaying; - (id)init { self = [super init]; if (self) { self.octive = 4; self.tempo = 120; self.length = 1; return self; } return nil; } - (void) play:(NSString *)music { DLog(#"%#", music); self.music = [[music stringByReplacingOccurrencesOfString:#"+" withString:#"#"] dataUsingEncoding: NSASCIIStringEncoding]; self.dataPos = 0; self.isPlaying = YES; [self playNote]; } - (void)stop { self.isPlaying = NO; } - (void)playNote { if (!self.isPlaying) return; if (self.dataPos > self.music.length || self.music.length == 0) { self.isPlaying = NO; return; } unsigned char *data = (unsigned char*)[self.music bytes]; unsigned int code = (unsigned int)data[self.dataPos]; self.dataPos++; switch (code) { case 65: // A case 66: // B case 67: // C case 68: // D case 69: // E case 70: // F case 71: // G { // Peak at the next char to look for sharp or flat bool sharp = NO; bool flat = NO; if (self.dataPos < self.music.length) { unsigned int peak = (unsigned int)data[self.dataPos]; if (peak == 35) // # { self.dataPos++; sharp = YES; } else if (peak == 45) // - { self.dataPos++; flat = YES; } } // Peak ahead for a length changes bool look = YES; int count = 0; int newLength = 0; while (self.dataPos < self.music.length && look) { unsigned int peak = (unsigned int)data[self.dataPos]; if (peak >= 48 && peak <= 57) { peak -= 48; int n = (count * 10); if (n == 0) { n = 1; } newLength += peak * n; self.dataPos++; } else { look = NO; } } // Pick the note length int length = self.length; if (newLength != 0) { DLog(#"InlineLength: %d", newLength); length = newLength; } // Create the note string NSString *note = [NSString stringWithFormat:#"%c", code]; if (sharp) note = [note stringByAppendingFormat:#"#"]; else if (flat) note = [note stringByAppendingFormat:#"-"]; // Set the tone generator freq [self setFreq:[self getNoteNumber:note]]; // Play the note [self.toneGen play:(self.tempo / length)]; } break; case 76: // L (length) { bool look = YES; int newLength = 0; while (self.dataPos < self.music.length && look) { unsigned int peak = (unsigned int)data[self.dataPos]; if (peak >= 48 && peak <= 57) { peak -= 48; newLength = newLength * 10 + peak; self.dataPos++; } else { look = NO; } } self.length = newLength; DLog(#"Length: %d", self.length); [self playNote]; } break; case 79: // O (octive) { bool look = YES; int newOctive = 0; while (self.dataPos < self.music.length && look) { unsigned int peak = (unsigned int)data[self.dataPos]; if (peak >= 48 && peak <= 57) { peak -= 48; newOctive = newOctive * 10 + peak; self.dataPos++; } else { look = NO; } } self.octive = newOctive; DLog(#"Octive: %d", self.self.octive); [self playNote]; } break; case 84: // T (tempo) { bool look = YES; int newTempo = 0; while (self.dataPos < self.music.length && look) { unsigned int peak = (unsigned int)data[self.dataPos]; if (peak >= 48 && peak <= 57) { peak -= 48; newTempo = newTempo * 10 + peak; self.dataPos++; } else { look = NO; } } self.tempo = newTempo; DLog(#"Tempo: %d", self.self.tempo); [self playNote]; } break; default: [self playNote]; break; } } - (int)getNoteNumber:(NSString*)note { note = [note uppercaseString]; DLog(#"%#", note); if ([note isEqualToString:#"A"]) return 0; else if ([note isEqualToString:#"A#"] || [note isEqualToString:#"B-"]) return 1; else if ([note isEqualToString:#"B"] || [note isEqualToString:#"C-"]) return 2; else if ([note isEqualToString:#"C"] || [note isEqualToString:#"B#"]) return 3; else if ([note isEqualToString:#"C#"] || [note isEqualToString:#"D-"]) return 4; else if ([note isEqualToString:#"D"]) return 5; else if ([note isEqualToString:#"D#"] || [note isEqualToString:#"E-"]) return 6; else if ([note isEqualToString:#"E"] || [note isEqualToString:#"F-"]) return 7; else if ([note isEqualToString:#"F"] || [note isEqualToString:#"E#"]) return 8; else if ([note isEqualToString:#"F#"] || [note isEqualToString:#"G-"]) return 9; else if ([note isEqualToString:#"G"]) return 10; else if ([note isEqualToString:#"G#"]) return 11; } - (void)setFreq:(int)note { float a = powf(2, self.octive); float b = powf(1.059463, note); float freq = roundf((275.0 * a * b) / 10); self.toneGen.frequency = freq; } - (void)toneStop { [self playNote]; } #end To play little tune create a Music object and play... [self.music play:#"T180 DF#A L2 A L4 O4 AA P4 F#F# P4 O3 D DF#A L2 A L4 O4 AA P4 GG P4 O3 C#C#EB L2 B L4 O4 BB P4 GG P4 O3 C#C#EB L2 B L4 O4 BB P4 F+F+ P4 O3 DDF#A L2 O4 D L4 O5 DD P4O4 AA P4 O3 DDF#A L2 O4 D L4 O5 DD P4O4 BB P4 EEG L8 B P8 ML B1 L4 MN G#A ML L3 O5 F#1L4 MN D O4 F# ML L2 F# MN L4 E ML L2 B MN L4 AD P8 D8 D4"]; Any idea on how to remove the chirp between notes?
I think that the bit where you stop audio output between notes is the culprit: if (self.toneUnit) { AudioOutputUnitStop(self.toneUnit); AudioUnitUninitialize(self.toneUnit); AudioComponentInstanceDispose(self.toneUnit); self.toneUnit = nil; } Just leave the tone unit active and you'll have less chirping. You'll need some other way to generate silence, probably by having RenderTone continue to run but generate amplitude zero. I was able to eliminate the slight chirps that remained by having it, on a frequency change, fade the amplitude down to nothing, update the frequenmcy, and fade back in again. This is of course what the old PC speaker couldn't do (except for a few people who rapidly switched it on again), but with a very rapid fade you can probably get the old-school effect without the chirps. Here's my fading RenderTone function (currently using evil global variables): double currentFrequency=0; double currentSampleRate=0; double currentAmplitude=0; OSStatus RenderTone( void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { // Fixed amplitude is good enough for our purposes const double amplitude = 0.5; // Get the tone parameters out of the view controller ToneGen *toneGen = (__bridge ToneGen *)inRefCon; double theta = toneGen.theta; BOOL fadingOut = NO; if ((currentFrequency != toneGen.frequency) || (currentSampleRate != toneGen.sampleRate)) { if (currentAmplitude > DBL_EPSILON) { fadingOut = YES; } else { currentFrequency = toneGen.frequency; currentSampleRate = toneGen.sampleRate; } } double theta_increment = 2.0 * M_PI * currentFrequency /currentSampleRate; // This is a mono tone generator so we only need the first buffer const int channel = 0; Float32 *buffer = (Float32 *)ioData->mBuffers[channel].mData; // Generate the samples for (UInt32 frame = 0; frame < inNumberFrames; frame++) { buffer[frame] = sin(theta) * currentAmplitude; //NSLog(#"amplitude = %f", currentAmplitude); theta += theta_increment; if (theta > 2.0 * M_PI) { theta -= 2.0 * M_PI; } if (fadingOut) { if (currentAmplitude > 0) { currentAmplitude -= 0.001; if (currentAmplitude < 0) currentAmplitude = 0; } } else { if (currentAmplitude < amplitude) { currentAmplitude += 0.001; if (currentAmplitude > amplitude) currentAmplitude = amplitude; } } } // Store the theta back in the view controller toneGen.theta = theta; return noErr; }
That little chirp is generally an artifact of mathematics. The ear essentially analyzes input signals in the frequency domain. A steady sine wave at frequency 220 Hz, for example, will sound like an A. However, when your sine wave is *un*steady, there are other frequencies that show up due to the boundary. In particular, you get a bit of a pop due to the very high frequency component of starting or stopping a sound abruptly. The way I solved this in my synthesizer (in Javascript, not Obj-C, but the concept here is the same) is to fade the sound in over 300 samples or so on note on, and fade the sound out over 300 samples or so on note off. There's no way to truly eliminate boundary effects other than not having a boundary at all, but even a small and imperceptible amount of fade will render the boundary effect imperceptible as well.
Compress / decompress string in memory
Can anyone provide me a tutorial / documentation on compressing and decompressing strings in memory in objective-c (for iPhone development). I am looking at Objective-Zip, but it only seems to work by writing the compressed data to a file.
give you an example #interface NSString (Gzip) - (NSData *)compress; #end #implementation NSString (Gzip) - (NSData *)compress { size_t len = [self length]; size_t bufLen = (len + 12) * 1.001; u_char *buf = (u_char *)malloc(bufLen); if (buf == NULL) { NSLog(#"malloc error"); return nil; } int err = compress(buf, &bufLen, (u_char *)[[self dataUsingEncoding:NSUTF8StringEncoding] bytes], len); if (err != Z_OK) { NSLog(#"compress error"); free(buf); return nil; } NSData *rtn = [[[NSData alloc] initWithBytes:buf length:bufLen] autorelease]; free(buf); return rtn; } #end