Repetition Pitch is the sensation of tonality in a sound, in which this tonal quality is solely obtained due to a repeated pattern, rather than a sinusoïdal waveform. Often this occurs when a sound is reflected against surfaces with equal intervals, for example a staircase. The effect is perceived most prominently if the reflected sound contains a wide spectrum of frequencies, such as traffic noise. Repetition Pitch has been described by Christiaan Huygens in a setting of the reflected sound of a fountain against a staircase.

An algorithm has been used to conceive an optimal staircase for reproducing this phenomenon, based on a given location of a sound source and listener and a frequency equivalent of the tone that is to be reproduced by the effect. The resulting sound of traffic noise as it sounds reflected against the staircase is given below. What will follow is quite a lengthy and technical outline of the workflow leading to the algorithm, staircase geometry and sound.

Sage has been used to generate an optimum staircase to induce tonality at a specified frequency. The problem that needed to be solved is that, if the risers of the stair are spaced equally, the difference in length between successively reflections would increase. The following script has been written to address this problem by solving a number of formulas, which describe the coordinates of the risers. The total length of a reflection, against a given riser, must be longer than the previous reflection by a specified amount (343/*f*, with *f* being the frequency of the induced tonality) and the step of the stair must be of a comfortable distance from the previous step (*dS*, set to 620mm). The other variables that need to be set are the position of the listener (*Lx*,*Ly*), sound source (*Sx*,*Sy*) and first riser (*Px*,*Py*).

# Script to calculate a sequence of stair steps # that reflect sound waves on the steps entering # the listener's ears successively with a fixed # interval. Distances are in meters. Sx,Sy = 1,1 # Location of sound source Lx,Ly = 3,10 # Location of listener Px,Py = 10,2 # Location of first step f = 880 # Repetition pitch frequency dS = 0.62 # Step size Ns = 20 # Number of steps # Initialize some other variables X,Y = Px,Py By,By = X,Y R1,R2,L = var('R1 R2 L') # Returns the four constraints to be solved def constraints(): return ( (X-Sx)**2 + (Y-Sy)**2 == R1**2, (X-Lx)**2 + (Y-Ly)**2 == R2**2, R1 + R2 == L, 2.4*(X-Px)**2 + 4.8*(Y-Py)**2 == dS**2, ) # Solve for the first three constraints to obtain the # length of the first reflection. Only accept positive measures for s in solve(constraints()[:-1],R1,R2,L,solution_dict=True): if len([v for v in s.values() if v < 0]): continue L = n(s[L]+343/f) break # Reinitialize variables X,Y,R1,R2 = var('X Y R1 R2') steps_ngon = [] steps_output = [] # Determine the position of the risers by solving # the constraints, accepting only solutions to the # upper right of the previous riser. for i in range(Ns): ss = solve(constraints(),X,Y,R1,R2,solution_dict=True) ss = [s for s in ss if s[X] > Px and s[Y] > Py] if not len(ss): break steps_ngon.append((Px,Py)) steps_ngon.append((Px,ss[0][Y])) steps_output.append((Px,Py)) Px = ss[0][X] Py = ss[0][Y] L += 343/f # Append the final riser steps_ngon.append((Px,Py)) steps_ngon.append((Px,By)) steps_output.append((Px,Py)) def pt(x,y,t): return point((x,y),color='black')+\ text(t,(x+0.15,y+0.15),color='black') show(polygon(steps_ngon,rgbcolor=(0.3,0.3,0.3))+pt(Sx,Sy,"S")+pt(Lx,Ly,"L"),figsize=11) print "coords=[" print "".join([" (%.6f,%.6f),\n"%s for s in steps_output])[:-2] print "]"

Running the script in sage results in the following output: a schematic overview of the generated staircase and a list of coordinates of the risers that can be loaded into blender to be subject of an acoustical analysis in E.A.R

coords=[ (10.000000,2.000000), (10.303411,2.184538), (10.600529,2.374127), (10.891426,2.568479), (11.176181,2.767327), (11.454880,2.970420), (11.727612,3.177525), (11.994465,3.388423), (12.255539,3.602907), (12.510927,3.820787), (12.760726,4.041883), (13.005034,4.266027), (13.243945,4.493060), (13.477556,4.722835), (13.705964,4.955210), (13.929258,5.190057), (14.147534,5.427252), (14.360882,5.666678), (14.569388,5.908228), (14.773140,6.151798), (14.972222,6.397290) ]

The coordinates can be turned into a geometrical staircase in blender by running the following script. The impulse response, as it is calculated by E.A.R, follows.

import bpy xs = [x for x,y in coords] ys = [y for x,y in coords] xs = sum([list(q) for q in zip(xs[:-1],xs[:-1])],[]) ys = sum([list(q) for q in zip(ys[:-1],ys[1:])],[]) zs = [0.0] * len(xs) vs = list(zip(xs,ys,zs)) es = [(x,x+1) for x in range(len(xs)-1)] me = bpy.data.meshes.new('stair') me.from_pydata(vs,es,[]) ob = bpy.data.objects.new('stair',me) scn = bpy.context.scene scn.objects.link(ob)

- Impulse response of adjusted risers

If evenly spaced riser were to be used, the spacing between the lobes in the impulse response would gradually increase. Rendering the impact of the repetition pitch much less pronounced. This can be demonstrated by instead generating a staircase in blender with the following sequence of coordinates.

dx,dy = 0.303411,0.184538 coords=[(10+dx*i,2+dy*i) for i in range(20)]

- Impulse response of evenly spaced risers

- Unprocessed traffic noise (courtesey of: freesound’s cognito perceptu)

- Repetition pitch, adjusted risers (click to play)

- Repetition pitch, evenly spaced risers (click to play)

- The example is two dimensional, but could easily be extended into 3d. The impulse responses in Blender are calculated using a staircase of one meter wide.
- The emitter of the sound is schematised as a point source, but the nature of traffic noise would have been captured captured better as a line source.
- In the calculation of the impulse responses, other environmental factors such as a ground plane have been neglected.