code: public String[] getAudioUrls() {
  		Audio[] audio = getAudio();
  
  		if (audio == null || audio.length == 0) {
  			return null;
  		}
  
  		String[] urls = new String[audio.length];
  
  		Environment env = getEnvironment();
  		Map<String, String> parameters = env.getHiddenParameters();
  		parameters.put(Environment.TARGET_ID, getTargetId());
  
  		if (Util.empty(getCacheKey())) {
  			// Add some randomness to the URL to prevent caching
  			String random = WebUtilities.generateRandom();
  			parameters.put(Environment.UNIQUE_RANDOM_PARAM, random);
  		} else {
  			// Remove step counter as not required for cached content
  			parameters.remove(Environment.STEP_VARIABLE);
  			parameters.remove(Environment.SESSION_TOKEN_VARIABLE);
  			// Add the cache key
  			parameters.put(Environment.CONTENT_CACHE_KEY, getCacheKey());
  		}
  
  		// this variable needs to be set in the portlet environment.
  		String url = env.getWServletPath();
  
  		for (int i = 0; i < urls.length; i++) {
  			parameters.put(AUDIO_INDEX_REQUEST_PARAM_KEY, String.valueOf(i));
  			urls[i] = WebUtilities.getPath(url, parameters, true);
  		}
  
  		return urls;
  	}
docs: Creates dynamic URLs that the audio clips can be loaded from. In fact the URL points to the main application
  servlet, but includes a non-null for the parameter associated with this WComponent (ie, its label). The
  handleRequest method below detects this when the browser requests a file.
  
  @return the urls to load the audio files from, or null if there are no clips defined