//  [python]
def create_wavenet_autoencoder(n_stages, n_layers_per_stage, n_hidden,
                               batch_size, n_skip, filter_length,
                               bottleneck_width, hop_length, n_quantization,
                               sample_rate):
    """Summary

    Parameters
    ----------
    n_stages : TYPE
        Description
    n_layers_per_stage : TYPE
        Description
    n_hidden : TYPE
        Description
    batch_size : TYPE
        Description
    n_skip : TYPE
        Description
    filter_length : TYPE
        Description
    bottleneck_width : TYPE
        Description
    hop_length : TYPE
        Description
    n_quantization : TYPE
        Description
    sample_rate : TYPE
        Description

    Returns
    -------
    TYPE
        Description
    """
    offset = n_quantization / 2.0
    sequence_length = 2**n_layers_per_stage * 2 * n_stages

    # Encode the source with 8-bit Mu-Law.
    X = tf.placeholder(
        name='X', shape=[batch_size, sequence_length], dtype=tf.float32)
    X_quantized = wnu.mu_law(X, n_quantization)
    X_scaled = tf.cast(X_quantized / offset, tf.float32)
    X_scaled = tf.expand_dims(X_scaled, 2)

    # The Non-Causal Temporal Encoder.
    en = wnu.conv1d(
        X=X_scaled,
        causal=False,
        num_filters=n_hidden,
        filter_length=filter_length,
        name='ae_startconv')

    # Residual blocks with skip connections.
    for i in range(n_stages * n_layers_per_stage):
        dilation = 2**(i % n_layers_per_stage)
        print(dilation)
        d = tf.nn.relu(en)
        d = wnu.conv1d(
            d,
            causal=False,
            num_filters=n_hidden,
            filter_length=filter_length,
            dilation=dilation,
            name='ae_dilatedconv_%d' % (i + 1))
        d = tf.nn.relu(d)
        en += wnu.conv1d(
            d,
            num_filters=n_hidden,
            filter_length=1,
            name='ae_res_%d' % (i + 1))

    en = wnu.conv1d(
        en, num_filters=bottleneck_width, filter_length=1, name='ae_bottleneck')

    en = wnu.pool1d(en, hop_length, name='ae_pool', mode='avg')
    encoding = en

    # The WaveNet Decoder.
    l = wnu.shift_right(X_scaled)
    l = wnu.conv1d(
        l, num_filters=n_hidden, filter_length=filter_length, name='startconv')

    # Set up skip connections.
    s = wnu.conv1d(l, num_filters=n_skip, filter_length=1, name='skip_start')

    # Residual blocks with skip connections.
    for i in range(n_stages * n_layers_per_stage):
        dilation = 2**(i % n_layers_per_stage)
        d = wnu.conv1d(
            l,
            num_filters=2 * n_hidden,
            filter_length=filter_length,
            dilation=dilation,
            name='dilatedconv_%d' % (i + 1))
        d = condition(d,
                      wnu.conv1d(
                          en,
                          num_filters=2 * n_hidden,
                          filter_length=1,
                          name='cond_map_%d' % (i + 1)))
        assert d.get_shape().as_list()[2] % 2 == 0
        m = d.get_shape().as_list()[2] // 2
        d_sigmoid = tf.sigmoid(d[:, :, :m])
        d_tanh = tf.tanh(d[:, :, m:])
        d = d_sigmoid * d_tanh
        l += wnu.conv1d(
            d, num_filters=n_hidden, filter_length=1, name='res_%d' % (i + 1))
        s += wnu.conv1d(
            d, num_filters=n_skip, filter_length=1, name='skip_%d' % (i + 1))

    s = tf.nn.relu(s)
    s = wnu.conv1d(s, num_filters=n_skip, filter_length=1, name='out1')
    s = condition(s,
                  wnu.conv1d(
                      en,
                      num_filters=n_skip,
                      filter_length=1,
                      name='cond_map_out1'))
    s = tf.nn.relu(s)

    # Compute the logits and get the loss.
    logits = wnu.conv1d(
        s, num_filters=n_quantization, filter_length=1, name='logits')
    logits = tf.reshape(logits, [-1, n_quantization])
    probs = tf.nn.softmax(logits, name='softmax')
    synthesis = tf.reshape(
        wnu.inv_mu_law(
            tf.cast(tf.argmax(probs, 1), tf.float32) - offset, n_quantization),
        [-1, sequence_length])
    labels = tf.cast(tf.reshape(X_quantized, [-1]), tf.int32) + int(offset)
    loss = tf.reduce_mean(
        tf.nn.sparse_softmax_cross_entropy_with_logits(
            logits=logits, labels=labels, name='nll'),
        0,
        name='loss')

    tf.summary.audio("synthesis", synthesis, sample_rate=sample_rate)
    tf.summary.histogram("probs", probs)
    tf.summary.histogram("input_quantized", X_quantized)
    tf.summary.histogram("logits", logits)
    tf.summary.histogram("labels", labels)
    tf.summary.histogram("synthesis", synthesis)
    tf.summary.scalar("loss", loss)
    summaries = tf.summary.merge_all()

    return {
        'X': X,
        'quantized': X_quantized,
        'encoding': encoding,
        'probs': probs,
        'synthesis': synthesis,
        'summaries': summaries,
        'loss': loss
    }